乐趣区

关于java:Java并发volatile关键字

大家好,这里是 淇妙小屋 ,一个分享技术,分享生存的博主
以下是我的主页,各个主页同步更新优质博客,创作不易,还请大家点波关注
掘金主页
知乎主页
Segmentfault 主页
开源中国主页
后续会公布更多 MySQL,Redis,并发,JVM,分布式等面试热点常识,以及 Java 学习路线,面试重点,职业规划,面经等相干博客
转载请表明出处!

1. volatile 的作用

1.1 保障变量的可见性

volatile 变量的批改对所有线程可见,体现在读,写两方面

  • 某个线程在本人的本地内存中批改 volatile 变量,会立即刷新到主内存中

  • 某个线程如果想要读取 volatile 变量,JMM 将该线程对应的本地内存设置为有效,该线程只能从主内存中获取

1.2 保障变量的单次读写具备原子性

对 volatile 变量的单次读写操作具备 原子性(JMM 不保障 64 位数据 double 或 long 的读写操作具备原子性),对于 i++ 这种复合操作,依然是没有原子性的

volatile 只保障变量的单次读写具备原子性,复合操作就没有原子性了

1.3 禁止指令重排序,保障有序性

  • 当程序执行到 volatile 变量的读操作或者写操作时,在其后面的操作的更改必定全副曾经进行,且后果曾经对前面的操作可见
  • 在进行指令优化时,不能将 volatile 语句与其余语句重排序

编译器在生成字节码时,会插入 内存屏障 来禁止指令冲排序

  • 每个 volatile 写操作——后面插入一个 StoreStore 屏障(StoreStore 保障达到 volatile 写时,后面的所有操作都曾经同步到主内存中了),前面插入一个 StoreLoad 屏障

  • 每个 volatile 读操作——后面插入 LoadLoad 和 LoadStore

2. volatile 实用场景

volatile 只能在无限的一些状况下应用 volatile 变量代替锁

  • 通过 CAS 对 volatile 变量进行写
  • 对变量的操作必须是原子的(i++ 这种不行)
退出移动版