Synchronized 关键字的使用
来源:互联网 发布:python write 换行 编辑:程序博客网 时间:2024/06/10 17:31
在单线程运行下无需使用同步方法,但是在多个线程访问同一块代码时就常常会出现以下问题:
1、线程冲突 : 多个线程操作相同的数据上的操作交替执行时就可能产生线程冲突如下代码。
package com.zrh.thread;public class Count {private int c = 0;public void increment(String threadName){System.out.println(threadName+"_before:"+c);c++;System.out.println(threadName+"_after:"+c);}public void decrement(String threadName){System.out.println(threadName+"_before:"+c);c--;System.out.println(threadName+"_after:"+c);}public int getValue(){return c;}}
开启两个线程操作同对象交替操作数据如下:
package com.zrh.thread;public class ThreadTest {public static void main(String[] args) throws InterruptedException {final Count count = new Count();Thread thread1 = new Thread(new Runnable() {public void run() {for (int i = 0; i < 100000; i++) {count.increment(Thread.currentThread().getName());}}});thread1.setName("incrementThread");Thread thread2 = new Thread(new Runnable() {public void run() {for (int i = 0; i < 100000; i++) {count.decrement(Thread.currentThread().getName());}}});thread2.setName("decremenetThread");thread1.start();thread2.start();Thread.sleep(10000);System.out.println("count:"+count.getValue());}}
打印结果中可以发现 理想结果是0,实际打印非0,说明在多个线程值交替的操作相同数据时就可能出现线程冲突,数据被覆盖的情况:
……
incrementThread_before:-14
incrementThread_after:-13
incrementThread_before:-13
incrementThread_after:-12
count:-12
2、内存一致性错误 : 也叫内存可见性错误。产生的原因是cpu对于任何的操作总是把数据从主存读到寄存器让后将结果写回到主存中,若在这个过程中有其他线程读取到主存中的数据。就可能会读到脏数据。
3.Synchronized的使用:为了避免以上两种情况,我们通常会用到synchronized关键字。Java有提供两种同步方式:同步方法和同步语句。
同步方法:只要在方法的声明中加上synchronized关键字。
package com.zrh.thread;public class SynchronizedCount {private int c = 0;public synchronized void increment(){c++;} public synchronized void decrement(){c--;}public synchronized int getValue(){return c;}}测试
package com.zrh.thread;public class ThreadTest {public static void main(String[] args) throws InterruptedException {final SynchronizedCount count = new SynchronizedCount();Thread thread1 = new Thread(new Runnable() {public void run() {for (int i = 0; i < 100000; i++) {count.increment();}}});thread1.setName("incrementThread");Thread thread2 = new Thread(new Runnable() {public void run() {for (int i = 0; i < 100000; i++) {count.decrement();}}});thread2.setName("decremenetThread");thread1.start();thread2.start();Thread.sleep(10000);System.out.println("count:"+count.getValue());}}运行结果如下,显然没有出现上面线程冲突的问题:
count:0
同步块:
syschronized(synObject){ //同步的代码块 }
有时我们并不需要将整个方法都同步,当这个方法比较大时这样操作是很影响效率,所以我们可以尽量之间需要同步的代码同步就好,这个时候就可以使用同步块,线程要执行同步块,必须要获得synObject的锁,同步块可以灵活的指定任意要上锁的对象。在同一时间只能有一个线程执行同步块的代码,其他线程可以执行非同步块的代码。
在用同步块时最好能够更细粒度的同步,如下面代码中的c1和从c2,这两个对象的操作互不干扰,这种情况就可以不必使用同步方法。我们可以创建两个"锁对象"。
package com.zrh.thread;public class MsLunch {private long c1 = 0;private long c2 = 0;private Object lock1 = new Object();private Object lock2 = new Object();public void inc1(){synchronized (lock1) {c1++;}}public void inc2(){synchronized (lock2) {c2++;}}}
4.内部锁与同步 :上面提交的synObject的锁指的是对象锁(也叫内部锁或监视锁的实体),在Java API规范中称为监视器。同步机制就是建立与对象锁上的,其实每个对象都有监视器,但在往常的代码执行中监视器并不会产生任何影响,只有在同步的范围内监视器才起作用。同步锁有两个方面的作用:1.对一个对象的排他性访问建立happen-before的关系。这对可见性是十分重要的。当一个线程需要排他性的访问一个对象的域时,线程首先要请求该对象的对象锁,在线程获得内部锁到释放内部锁的这段时间里,我们就说该线程持有这个对象锁。当访问结束线程释放内部锁,在此之前其它线程将不能获得对象锁,如果其它线程尝试获得该对象锁,就会被阻塞。
- synchronized关键字的使用
- synchronized关键字的使用 .
- synchronized 关键字的使用
- synchronized 关键字的使用
- Synchronized关键字的使用
- synchronized关键字的使用
- Synchronized 关键字的使用
- Java Synchronized关键字的使用
- synchronized关键字的详细使用
- 同步线程的synchronized关键字的使用
- 黑马程序员-synchronized关键字的使用总结
- java线程以及synchronized关键字的使用
- java_Thread中synchronized关键字的使用
- Java多线程同步 synchronized 关键字的使用
- Java中synchronized关键字的使用
- java 使用synchronized关键字锁定的对象
- JAVA 线程中的synchronized关键字的使用
- 同步锁synchronized 关键字的使用效果
- [Javascript学习101]:Promise.then里继续使用异步
- iOS 调用设备震动
- windows 10中的ubuntu子系统安装桌面环境的方法(How to install Ubuntu-desktop in windows 10 Subsystem for Linux)
- node 异步/同步文件删除
- java 常见问题总结
- Synchronized 关键字的使用
- Oracle中的硬解析和软解析
- C#之使用NotifyIcon实现任务栏托盘菜单,图标闪烁效果及气泡提示 很多程序是只需要后台运行的,甚至不需要自己的应用界面。NotifyIcon提供了程序在任务栏的显示功能 程序下载链接如下
- 最全的 SqlHelper 类
- [Selenium] Selenium定向爬取海量精美图片及搜索引擎杂谈
- 2.5 方案/协议列表
- getAttribute/setAttribute的使用
- Binary Tree DFS Template
- C++中的dll和lib