可以保证多线程的 可见性、有序性,不能保证原子性
为什么不能保证原子性
每个单独的读写操作都会及时刷新到主存中,后续操作如果失败,没有什么回滚机制(感觉理所当然,但是现在行业卷,面试时就要问你zzz)
怎么保证可见性的
内存屏障保证的。什么是内存屏障?就是一条特殊的 cpu 指令,lock 前缀指令。
当线程 A 对 volatile 变量执行了写操作,会发一条 lock 前缀指令把工作内存的值刷到主存中,保证当前线程与主存中的值一致
当线程 B 对 volatile 变量执行读操作时也会发送一条 lock 前缀指令获取主存的最新值吗?肯定不是的,不然直接 volatile 变量每次都操作主存得了;还有就是如果别的线程不更改值呢,不就可以一直使用当前线程缓存的值吗。原因是:缓存一致性协议(MESI),线程A刷新了主存,线程B就知道当前缓存值过期了,这时才去读主存的值
怎么保证有序性的
也是内存屏障保证的。和 lock 类似,lock 前缀指令就会刷新主存,编译器会在适当的位置会插入内存屏障指令来禁止重排序
volatile 应用场景
- AQS(volatile+cas保证线程安全)
- 双重检查(double-checked)
class Singleton {
private volatile static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
syschronized(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}