在Java语言里,Happen-Before的语义本质上是一种可见性,A Happen Before B意味着A事件对于B事件来说是可见的,无论A事件还是B事件是否发生在同一个线程里。例如A事件发生在线程1上,B事件发生在线程2上,Happen Before规则能够保证线程2也能看到A事件的发生。
1.程序的顺序性规则
指在一个线程中,按照程序顺序,前面的操作Happen-Before于后续的任意操作。
class VolatileExample {
int x = 0;
volatile boolean v = false;
public void writer() {
x = 42; //#1
v = true; //#2
}
}
例如上面的代码,对于同一个线程而言,“x=42” Happen-Before “v=true”
2.volatile变量规则
指对一个volatile变量的写操作,Happen-Before与对这个变量的读操作
3.传递性
如果A Happen-Before B,并且B Happen-Before C, 则A Happen-Before C
4.管程中锁的规则
指对一个锁的解锁Happen-Before与后续对这个锁的加锁操作
5.线程start规则
指父线程A启动子线程B之后,子线程B能够看到父线程在启动子线程B之前的操作
Thread B = new Thread(()->{
// 主线程调用 B.start() 之前
// 所有对共享变量的修改,此处皆可见
// 此例中,var==77
});
// 父线程对共享变量 var 修改
var = 77;
// 父线程启动子线程
B.start();
6.线程join规则
是指父线程 A 等待子线程 B 完成(父线程 A 通过调用子线程 B 的 join() 方法实现),当子线程 B 完成后,父线程能够看到子线程B的操作。
Thread B = new Thread(()->{
// 此处对共享变量 var 修改
var = 66;
});
// 例如此处对共享变量修改,
// 则这个修改结果对线程 B 可见
// 主线程启动子线程
B.start();
B.join()
// 子线程所有对共享变量的修改
// 在主线程调用 B.join() 之后皆可见
// 此例中,var==66