volatile关键字
语义
一个共享变量被volotile
关键词修饰之后,就具备了以下两层语义:
- 保证了不同线程对该变量值操作的可见性
- 禁止jvm进行指令重排序
语义1的解释:
- 用了volatile修饰的变量值一经修改就会马上写入主存。
- 用了volatile修饰的变量值一经修改,其他线程的工作内存中的缓存值会马上失效。
- 用了volatile修饰的变量值工作内存中的缓存值失效了再使用新值时,会去主存中获取。
- 以此保证可见性。
语义2的解释:
- 保证了有序性
正所谓天道有缺(hhh),volatile
把并发的三个问题:原子性,可见性,有序性。解决了两,但是原子性是它解决不了的哦。
原因是因为:由之前的解释可知,在线程1更改了变量值之后,线程2会马上得到更新的值,但是在线程1取到值还未更新值之前,线程2更新值了,线程1更新值了,就出问题了撒。比如i++操作。
这里注意,synchronized和Lock是可以保证原子性的。另外unsafe类里面的cas也可以保证原子性,concurrent包里面很多工具就是通过volatile+cas来解决三个问题的。
volatile
使用场景
关键点在于volatile于并发场景中,无法解决不能保证原子性的问题,所以理论上来讲满足了一下两个条件,可用于替代锁。
- 对于变量的写操作不依赖于当前值
比如i++这种自增计数器就不行 - 该变量没有包含在其他变量的不定式中
如(end>=start)
一般的使用场景:
- 状态标记量
- 单列模式的double check
避免单列模式取到getInstance取到一个并未完全初始化的对象(构造方法只执行了一半) - 独立观察
如记录最近访客,这种可以给所有线程共享的实时更新值 - 读写策略
如果读操作频率远超写操作,可以给写操作加上锁。