Volatile
Volatile关键词有什么作用?
1.内存可见性;
2.禁止指令重排序。
换个思路:
redis应该大部分人都用过,当一个查询很频繁的时候,可以把数据缓存到redis,
这样查询直接走缓存,不查数据库了。
当你修改了数据库记录后,会造成与redis中的数据不一致,这就需要在你修改
数据库的同时,要么同时更新缓存,要么直接把缓存清空,下次查询会自动同步缓存。
再来看看volatile:
cpu正常情况下不和内存交互而是和高速缓存打交道,这里内存就相当于宏观上的数据库,
高速缓存就相当于宏观上的redis。
Volatile关键词的语义分析
volatile作用:让其他线程能够马上感知到某一线程多某个变量的修改
(1)保证可见性
对共享变量的修改,其他的线程马上能感知到
不能保证原子性 读、写、(i++)
(2)保证有序性
重排序(编译阶段、指令优化阶段)
输入程序的代码顺序并不是实际执行的顺序
重排序后对单线程没有影响,对多线程有影响
Volatile的使用场景
(1)状态标志(开关模式)
public class ShutDowsnDemmo extends Thread{ private volatile boolean started=false; @Override public void run() { while(started){ dowork(); } } public void shutdown(){ started=false; } } |
(2)双重检查锁定(double-checked-locking)
public class Singleton { private volatile static Singleton instance; public static Singleton getInstance(){ if(instance==null){ synchronized (Singleton.class){ instance=new Singleton(); } } return instance; } } |
Volatile和synchronized的区别
(1)使用上的区别
Volatile只能修饰变量,synchronized只能修饰方法和语句块
(2)对原子性的保证
synchronized可以保证原子性,Volatile不能保证原子性
(3)对可见性的保证
都可以保证可见性,但实现原理不同
Volatile对变量加了lock,synchronized使用monitorEnter和monitorexit monitor JVM
(4)对有序性的保证
Volatile能保证有序,synchronized可以保证有序性,但是代价(重量级)并发退化到串行
(5)其他
synchronized引起阻塞
Volatile不会引起阻塞
Volatile的使用限制
由于volatile变量只能保证可见性,在不符合以下两条规则的运算场景中,我们仍然要通过加锁(使用synchronized或java.util.concurrent中的原子类)来保证原子性。
- 运算结果并不依赖变量的当前值,或者能够确保只有单一的线程修改变量的值。
- 变量不需要与其他的状态变量共同参与不变约束。