Java 并发编程系列- volatile
volatile 变量的特性
保证可见性,不保证原子性:
� 当写一个 volatile 变量时,JMM 会把该线程本地内存中的变量强制刷新到
主内存中去;
� 这个写操作会导致其他线程中的 volatile 变量缓存无效。
禁止指令重排,我们回顾一下,重排序需要遵守一定规则:
� 重排序操作不会对存在数据依赖关系的操作进行重排序。比如:a=1;b=a;
这个指令序列,由于第二个操作依赖于第一个操作,所以在编译时和处理器运行
时这两个操作不会被重排序。
� 重排序是为了优化性能,但是不管怎么重排序,单线程下程序的执行结果
不能被改变。比如:a=1;b=2;c=a+b 这三个操作,第一步(a=1)和第二步(b=2)由
于不存在数据依赖关系, 所以可能会发生重排序,但是 c=a+b 这个操作是不会
被重排序的,因为需要保证最终的结果一定是 c=a+b=3。
volatile 禁止指令重排规则
使用 volatile 关键字修饰共享变量便可以禁止这种重排序。若用 volatile 修饰共
享变量,在编译时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排
序,volatile 禁止指令重排序也有一些规则:
� 当程序执行到 volatile 变量的读操作或者写操作时,在其前面的操作的更
改肯定全部已经进行,且结果已经对后面的操作可见;在其后面的操作肯定还没
有进行;
� 在进行指令优化时,不能将对 volatile 变量访问的语句放在其后面执行,
也不能把 volatile 变量后面的语句放到其前面执行。
即执行到 volatile 变量时,其前面的所有语句都执行完,后面所有
语句都未执行。且前面语句的结果对 volatile 变量及其后面语句可
见。
volatile 禁止指令重排分析
该部分相关内容,我直接 copy 上一篇文章,不是为了凑篇幅,因
为有同学没有看上一篇文章,直接看这篇,为了能让每一篇文章能
独立成章,可能会引用之前文章中的内容。
先看下面未使用 volatile 的代码: