volatile内存语义
volatile是java提供的一种轻量级的同步机制,在并发编程中,它也扮演着比较重要的角色。一方面volatile不会造成上下文切换的开销,另一方面它又不能像synchronized那样保证所有场景下线程安全,因此必须在合适的场景下使用volatile机制。
valatile仅保证了可见性和有效性,并不能保证原子性
volatile原理
volatile能够实现可见性和有序性,flush和reflush指令解决了可见性,内存屏障解决了有序性。
flush和reflush指令
flush和reflush指令解决了可见性。
- flush:当读取数据时强制将无效队列中invalidate message刷新到高速缓存标记数据为无效重新从其他处理器高速缓存和主存中读取
- reflush:当写数据时强制将写缓冲区的数据写入到高速缓存中
volatile写-读的内存语义
- 当写一个volatile变量时,JMM会把该线程对应的本地内存中的变量值刷新到主内存。
- 当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效,线程将从主内存中读取共享变量。
内存屏障
内存屏障解决了有序性
volatile读数据
loadload屏障:禁止下面普通读和volatile读重排
loadStore屏障:禁止下面普通写和volatile读重排
在每个volatile读操作的后面插入一个LoadLoad屏障。在每个volatile读操作的后面插入一个LoadStore屏障。
volatile写数据
在每个volatile写操作的前面插入一个StoreStore屏障。在每个volatile写操作的后面插入一个StoreLoad屏障。
- 前面storestore屏障:禁止上面普通写和volatile写重排序 解决store和store的重排
- 后面storeload屏障:禁止下面普通读和volatile读/写重排序 解决store和load的重排
volatile的应用场景
- 优雅停机isRunning中断线程后修改isRunning=false volatile
- aqs中state变量保证另外一个线程读时可见
- CopyOnWriteArrayList写时复制中数组对象通过volatile修饰保证写操作在下次读的时候可见
- 注册中心心跳