原创

volatile与JMM

温馨提示:
本文最后更新于 2025年06月04日,已超过 374 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

2大特点

可见性

有序性-->有时需要禁止重排

内存语义

当写一个volatile变量时,JMM会把该线程的本地内存中的共享变量值 立即刷新回主内存中

当读一个volatile变量时,JMM会把该线程对应的本地内存设置为无效,重新回到主内存中读取最新共享变量的值

所以volatile的写内存语义是直接刷新到主内存,读的没存语义是直接从主内存中读取

保证可见性和有序性

内存屏障  Memory Barrier

写屏障(Store Memory Barrier):告诉处理器在写屏障之前将所有存储在缓存(store buffers)中的数据同步到主内存。就是说 当看到Store屏障指令,就必须把该指令之前所有写入指令执行完毕才能继续往下执行

读屏障(Load Memory Barrier):处理器在读屏障之后的读操作,都在读屏障之后执行。在Load屏障指令之后能够保证后面的读取指令一定能读到最新的数据

对于一个volatile变量的写,先行发生于这个volatile变量的读,也叫 写后读。

保证可见性:保证不同线程对 某个变量完成操作后结果及时可见,即该共享变量一旦改变所有线程立即可见


细分4种屏障

loadload:读读屏障

storeload:写读屏障

loadstore:读写屏障

loadload:写写屏障



volatile变量不适合参与到依赖当前值的运算


原因:JVM的字节码,i++分成三步,间隙期不同步非原子操作

重排序

存在数据依赖关系,禁止重排序===>重排序发生,会导致程序运行结果不同。如

  1. 写后读
  2. 写后写
  3. 读后写

数据依赖性:若两个操作访问统一变量,且这两个操作中有一个为写的操作,此时量操作间就存在数据依赖性

指令禁重排

第一 为volatile 读,第二 不论

第二 为volatile 写,第一不论

第一 为volatile 写,第二 为volatile 读,

这几种皆不能重排序

volatile使用场景

单一赋值(不可用于 复合运算 i++类)

状态标志

开销低的读写策略

DCL双端锁

 











正文到此结束