原子性(Atomicity)
概念:
- 对基本数据类型的读取和赋值操作是原子性操作
分析代码:
i = 2; \\1
j = i; \\2
i++; \\3
i = i + 1; \\4- 原子性操作:
- 1 . 读取操作
- 非原子操作
- 2、3、4
- 对于2:先读取i,在写入j
- 对于3:点读厚些
- 对于4:同上
可见性(Visibility)
- Java就是利用
volatile来提供可见性的,当一个变量被volatile
有序性(Ordering)
- JMM是允许编译器和处理器对指令重排序的。
- 但是规定了
as-if-serial
比如下面的程序段
int a = 0;
boolean flag = false;
public void write(){
a = 2; \\1
flag = true; \\2
}
public void multify(){
if (flag) \\3
int ret = a * a;\\4
}分析:
- 若两线程A、B执行上面的代码,A先执行
write(),B在执行multify(), 最后ret == 4 -
write方法里的 1和 2做了重排序,线程 1先对flag赋值为true,随后执行到线程 2,ret直接计算出结果,再到线程 1, -这时候a
解决:
- 这时候可以为
flag加上volatile关键字,禁止重排序,可以确保程序的“有序性”,也可以上重量级的synchronized和Lock
JMM具备一些先天的有序性,即不需要通过任何手段就可以保证的有序性
happens-before
以下是定义的规则
1. 程序顺序规则:一个线程中的每个操作,happens-before于该线程中的任意后续操作
2. 监视器锁规则:对一个线程的解锁,happens-before于随后对这个线程的加锁
3. volatile变量规则:对一个volatile域的写,happens-before于后续对这个volatile域的读
4. 传递性:如果A happens-before B ,且 B happens-before C, 那么 A happens-before C
5. start()规则:如果线程A执行操作ThreadBstart()(启动线程B) , 那么A线程的
6. ThreadBstart()happens-before 于B中的任意操作
7. join()原则:如果A执行ThreadB.join()并且成功返回,
那么线程B中的任意操作happens-before于线程A从ThreadB.join()操作成功返回。
8. interrupt()原则:对线程interrupt()方法的调用先行发生于被中断线程代码检测到中断事件的发生,
可以通过Thread.interrupted()方法检测是否有中断发生.
9. finalize()原则:一个对象的初始化完成先行发生于它的finalize()方法的开始续:volatile关键字如何满足并发编程的三大特性的?
















