happen-before 原则令人看了之后一头雾水,感觉理解了 ,又感觉搞不懂。如下
- 程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作
- 锁定规则:一个unLock操作先行发生于后面对同一个锁额lock操作
- volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作
- 传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C
- 线程启动规则:Thread对象的start()方法先行发生于此线程的每个一个动作
- 线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生
- 线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行
- 对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始
这里重点讨论下 ,volatile变量的这个说法 : 写优先发生于后面的读。这句到底是什么意思?
- 首先一点 ,指定了volatile的变量,他前面的代码不能和他本身的写操作重排序, 他后面的代码,不能和他前面的代码重排序。
// Definition: Some variables
// 变量定义
private int first = 1;
private int second = 2;
private int third = 3;
private volatile boolean hasValue = false;
// First Snippet: A sequence of write operations being executed by Thread 1
//片段 1:线程 1 顺序的写操作
first = 5;
second = 6;
third = 7;
hasValue = true;
// Second Snippet: A sequence of read operations being executed by Thread 2
//片段 2:线程 2 顺序的读操作
System.out.println("Flag is set to : " + hasValue);
System.out.println("First: " + first); // will print 5 打印 5
System.out.println("Second: " + second); // will print 6 打印 6
System.out.println("Third: " + third); // will print 7 打印 7
上面的几行代码,用来解释上面那句话 。
hasValue
不能和他上面的任何一句重排序。 下面的打印hasvalue的 不能和 他下面的任何一句重排序。
除了上面的作用 。还有一个作用: 就是对写优先读的准确解释 : 多个线程操作volatile变量的时候,访问这个变量的线程总能读到最后一个对他写的线程的最终值。 下面的例子来说明这个问题
public static volatile int count = 0;
public static void main(String[] args) {
//
new Thread(new Runnable() {
@Override
public void run() {
while (count == 0) {
}
System.out.println("886");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
count = 2;
}
}).start();
}
测试后会发现 ,如果count不是volatile类型的 ,第一个线程的while循环不会终止。while会一直使用他自己线程读取到的值,不会去更新,也就是说他看不到前面线程对这个变量的修改。 如果使用volatile来修饰,后面一个线程对他进行写入操作了,第一个线程在下一个while循环立刻就能读到 。死循环立刻就终止了 。
这就是这句话的含义: 对一个变量的写操作先行发生于后面对这个变量的读操作
网友评论