继上一篇:多线程安全问题:可见性、原子性、有序性
引言
- Happens-Before 的语义本质上是一种可见性
A Happens-Before B 意味着 A 事件对 B 事件来说是可见的,无论 A 事件和 B 事件是否发生在同一个线程里。 - 三个关键字:synchronized、volatile、final
什么是Java内存模型
Java内存模型规范了JVM如何按需禁用内存和编译优化
具体包括:三个关键字(synchronized、volatile、final)及Happens-Before原则
Volatile关键字
- 原始语义,如 volatile int x = 0,表达的是:告诉编译器,对这个变量的读写,不能使用 CPU 缓存,必须从内存中读取或者写入。
final关键字
- final 修饰变量时,初衷是告诉编译器:这个变量生而不变,可以可劲儿优化。
- 避免构造函数 ”逸出“
final int x;
public FinalFieldExample() {
x = 3;
y = 4;
global.obj = this; // this逸出;线程通过 global.obj 读取 x 有可能读到 0
}
Happens-Before原则
- 前面一个操作的结果对后续操作是可见的
- 具体规则:
- 程序的顺序性规则:程序前面对某个变量的修改一定是对后续操作可见的
- Volatile变量规则:对一个 volatile 变量的写操作, Happens-Before 于后续对这个 volatile 变量的读操作
- 传递性规则:如果 A Happens-Before B,且 B Happens-Before C,那么 A Happens-Before C
- 管程锁规则:对一个锁的解锁 Happens-Before 于后续对这个锁的加锁。
- 线程start()规则:如果线程 A 调用线程 B 的 start() 方法,那么该start() 操作 Happens-Before 于线程 B 中的任意操作。
- 线程join()规则:如果在线程 A 中,调用线程 B 的 join() 并成功返回,那么线程 B 中的任意操作 Happens-Before 于该 join() 操作的返回
- 线程interrupt()规则:对线程interrupt() 方法的调用先行发生于被中断线程的代码检测到中断事件的发生
- 对象finalize规则:一个对象的初始化完成先行发生于他的finalize() 方法的开始
重点:Volatile变量规则
网友评论