Java中竞态条件和使用synchronized关键字同步
2018-01-17 16:37
381 查看
首先举一个例子:
定义一个 CountThread 类,如下,在 run 函数中进行全局变量的自增操作。
调用的测试类如下:
运行结果如下(截取部分):
根据截取的部分可以看到某些线程,执行 count++ 后输出了同样的结果,比如 Thread-18 和 Thread-19,二者均输出 20。同样还有 Thread-985 和 Thread-986,二者均输出 984。造成这个问题的原因就是自增操作并不是原子性的,自增的方法要分为如下的三步来执行:
如果A线程在执行完第一步后,CPU交给B线程来执行,B线程也将 count 的值读入寄存器,此时,AB两个线程中 count 的值是一样的,A,B两个线程执行完后,返回的结果是同一个结果。
将程序进行修改,加入 synchronized 关键字:
测试程序不变,运行后,结果如下:
我们可以看到,Thread 的编号并不是按照先后顺序来执行的,这是因为先 start() 方法的线程并不一定先执行,而是由于CPU执行某个线程是具有不确定性的。
这里的结果,说明加入了 synchronized 关键字后,所有线程在同步方法中,是每次只有一个在执行的。最终结果也是正确的。
定义一个 CountThread 类,如下,在 run 函数中进行全局变量的自增操作。
public class CountThread extends Thread{ private int count = 0; @Override public void run() { count++; System.out.println(Thread.currentThread().getName() + " - " + count); } }
调用的测试类如下:
public class Run { public static void main(String[] args) throws InterruptedException{ CountThread countThread = new CountThread(); for(int i=0; i<1000; i++){ Thread thread = new Thread(countThread); thread.start(); } } }
运行结果如下(截取部分):
Thread-1 - 1 Thread-2 - 3 Thread-3 - 2 Thread-4 - 4 Thread-5 - 5 Thread-8 - 6 Thread-7 - 7 Thread-11 - 8 Thread-17 - 12 Thread-21 - 13 Thread-15 - 14 Thread-23 - 16 Thread-10 - 17 Thread-14 - 18 Thread-18 - 20 Thread-19 - 20 ... Thread-980 - 978 Thread-981 - 979 Thread-983 - 981 Thread-982 - 981 Thread-984 - 982 Thread-986 - 984 Thread-985 - 984 Thread-989 - 985 Thread-987 - 986 Thread-990 - 987 Thread-991 - 988 Thread-993 - 989 Thread-994 - 990 Thread-995 - 992 Thread-992 - 993 Thread-988 - 991 Thread-996 - 994 Thread-997 - 995 Thread-999 - 997 Thread-998 - 996 Thread-1000 - 998
根据截取的部分可以看到某些线程,执行 count++ 后输出了同样的结果,比如 Thread-18 和 Thread-19,二者均输出 20。同样还有 Thread-985 和 Thread-986,二者均输出 984。造成这个问题的原因就是自增操作并不是原子性的,自增的方法要分为如下的三步来执行:
一.将 count 的值读入寄存器中; 二.将 count 加 1; 三.将 count 保存回内存中。
如果A线程在执行完第一步后,CPU交给B线程来执行,B线程也将 count 的值读入寄存器,此时,AB两个线程中 count 的值是一样的,A,B两个线程执行完后,返回的结果是同一个结果。
将程序进行修改,加入 synchronized 关键字:
public class CountThread extends Thread{ private int count = 0; @Override public synchronized void run() { count++; System.out.println(Thread.currentThread().getName() + " - " + count); } }
测试程序不变,运行后,结果如下:
Thread-1 - 1 Thread-6 - 2 Thread-5 - 3 Thread-8 - 4 Thread-4 - 5 Thread-10 - 6 Thread-3 - 7 Thread-2 - 8 Thread-12 - 9 Thread-11 - 10 ... Thread-980 - 980 Thread-981 - 981 Thread-982 - 982 Thread-983 - 983 Thread-984 - 984 Thread-985 - 985 Thread-986 - 986 Thread-987 - 987 Thread-988 - 988 Thread-989 - 989 Thread-990 - 990 Thread-991 - 991 Thread-992 - 992 Thread-993 - 993 Thread-994 - 994 Thread-995 - 995 Thread-996 - 996 Thread-997 - 997 Thread-998 - 998 Thread-999 - 999 Thread-1000 - 1000
我们可以看到,Thread 的编号并不是按照先后顺序来执行的,这是因为先 start() 方法的线程并不一定先执行,而是由于CPU执行某个线程是具有不确定性的。
这里的结果,说明加入了 synchronized 关键字后,所有线程在同步方法中,是每次只有一个在执行的。最终结果也是正确的。
相关文章推荐
- Java同步机制总结--synchronized关键字的使用
- java多线程编程之使用Synchronized关键字同步类方法
- Java多线程初学者指南(10):使用Synchronized关键字同步类方法
- Java中使用同步关键字synchronized需要注意的问题
- 记录Java多线程的同步问题---synchronized关键字的使用
- 九、初学Java多线程:使用Synchronized关键字同步类方法
- Java中使用同步关键字synchronized需要注意的问题
- Java多线程初学者指南(10):使用Synchronized关键字同步类方法
- java同步静态方法与非静态方法(使用synchronized关键字)
- 初学Java多线程:使用Synchronized关键字同步类方法
- Java多线程初学者指南(10):使用Synchronized关键字同步类方法
- Java中使用同步关键字synchronized需要注意的问题
- java多线程-竞态条件的形成模拟,锁的使用,volatile关键字的使用
- (转)初学Java多线程:使用Synchronized关键字同步类方法
- 初学Java多线程:使用Synchronized关键字同步类方法
- Java多线程初学者指南(10):使用Synchronized关键字同步类方法
- java线程同步——条件对象+synchronized 关键字
- Java中使用synchronized关键字实现简单同步操作示例
- Java多线程初学者指南(10):使用Synchronized关键字同步类方法
- 并发编程学习总结(八) :java中synchronized关键字使用详解 对象锁的相关条件的使用(2)