【并发编程】- Java内存模型-Happens-Before规则

学习王宝令老师的《Java并发编程实战》记录的学习笔记。

Java内存模型规范了JVM如何提供按需禁用缓存和编译优化的方法。
具体来说,这些方法包括volatile、synchronized和final三个关键字,以及六项Happens-Before规则。

Happens-Before规则

Happens-Before : 前一个操作的结果对后续操作是可见的

1. 程序的顺序性规则

这条规则是指在一个线程中,按照程序顺序,前面的操作Happens-Before于后续任意操作。

2. volatile变量规则

这条规则是指对一个volatile变量的写操作,Happens-Before于后续对这个volatile变量的读操作。

3. 传递性

这条规则是指A Happens-Before B ,且 B Happens-Before C ,那么 A Happens-Before C。

4. 管程中锁的规则

这条规则是指对一个锁的解锁Happens-Before于后续对这个锁的加锁。

synchronized (this) { //此处自动加锁
  // x是共享变量,初始值=10
  if (this.x < 12) {
    this.x = 12; 
  }  
} //此处自动解锁

管程中锁的规则,可以这样理解:假设 x 的初始值是 10,线程 A 执行完代码块后 x 的值会变成 12(执行完自动释放锁),线程 B 进入代码块时,能够看到线程 A 对 x 的写操作,也就是线程 B 能够看到 x==12。这个也是符合我们直觉的,应该不难理解。

5. 线程start()规则

这条是关于线程启动的。它是指主线程A启动子线程B后,子线程B能够看到主线程在启动子线程B前的操作。

换句话说就是,如果线程 A 调用线程 B 的 start() 方法(即在线程 A 中启动线程 B),那么该 start() 操作 Happens-Before 于线程 B 中的任意操作。

换句话说就是,如果线程 A 调用线程 B 的 start() 方法(即在线程 A 中启动线程 B),那么该 start() 操作 Happens-Before 于线程 B 中的任意操作

6. 线程join()规则

这条是关于线程等待的。它是指主线程A等待子线程B完成(主线程A通过调用子线程B的join()方法实现),当子线程B完成后(主线程A中join()方法返回),主线程能够看到子线程的操作。 当然所谓的“看到”,指的是对共享变量的操作。
换句话说就是,如果在线程 A 中,调用线程 B 的 join() 并成功返回,那么线程 B 中的任意操作 Happens-Before 于该 join() 操作的返回。


Thread B = new Thread(()->{
  // 此处对共享变量var修改
  var = 66;
});
// 例如此处对共享变量修改,
// 则这个修改结果对线程B可见
// 主线程启动子线程
B.start();
B.join()
// 子线程所有对共享变量的修改
// 在主线程调用B.join()之后皆可见
// 此例中,var==66

final

讲过 volatile 为的是禁用缓存以及编译优化,我们再从另外一个方面来看,有没有办法告诉编译器优化得更好一点呢?这个可以有,就是 final 关键字。

final修饰变量,初衷是告诉编译器:这个变量生而不变,可以可劲儿优化。

你可能感兴趣的:(【并发编程】- Java内存模型-Happens-Before规则)