java语言天生有一个 先行发生原则,无须借助任何同步器就存在 这是判断线程是否存在竞争,线程是否安全的主要依据,
1、程序次序规则:在一个线程内,书写在前面的代码先行发生于后面的。确切地说应该是,按照程序的控制流顺序,因为存在一些分支结构。
2、管程锁定规则。一个unlock操作先行发生于后面对同一个锁的lock操作。
3、Volatile变量规则:对一个volatile修饰的变量,对他的写操作先行发生于读操作。
4、线程启动规则:Thread对象的start()方法先行发生于此线程的每一个动作。
5、线程终止规则:线程的所有操作都先行发生于对此线程的终止检测。
6、线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码所检测到的中断事件。
7、对象终止规则:一个对象的初始化完成(构造函数之行结束)先行发生于发的finilize()方法的开始。
8、传递性:A先行发生B,B先行发生C,那么,A先行发生C。
例子(先行发生原则分析):
private int value = 0;
private void setValue(int value) {
this.value = value;
}
private int getValue() {
return value;
}
假设存在线程A和线程B,线程A先(时间上的先后)调用了setValue(1),然后线程B调用了同一对象的getValue(), 线程B收到的值
我们按照先行原则分析下:
由于两个方法分别由线程A,B调用不在同一线程中,不满足程序次序规则,
没有同步锁,不会发生lock,unlock操作,故不满足管道规则
value没有volatile修饰,也不满足volatile变量原则
后面的线程启动终止中断,和对象终结规则也挨不上边
通过以上分析可以得出value变量是线程不安全的
摘自《深入理解java虚拟机12.3.6 先行发生原则》