JUC-JMM与volatile关键字

volatile简介及作用

volatile是JVM提供的轻量级的同步机制。volatile关键字能够保证并发编程的三大特性中的可见性,有序性。但是不能保证原子性。

保证可见性:

经过volatile修饰的变量,在本地内存中修改之后,会立即刷回主内存中。当主内存中的共享变量修改之后,其他线程的本地内存会立即同步获取到这个最新的值。

保证有序性:

通过禁止指令重排优化来保证有序性。禁止指令重排优化是通过内存屏障来实现的。

内存屏障

内存屏障就是CPU或者编译器对内存随机访问的一个同步点,使得对该点之前的操作在该点之后的操作之前。避免代码重排序。

内存屏障粗分类:

  • 读屏障:在读操作之前插入读屏障,让工作内存中的缓存失效,进而从主存中获取最新的数据。
  • 写屏障:在写操作之后插入写屏障,让工作内存中的缓存立即写入到主内存中去。

内存屏障细分类:

LoadLoad: 保证load1在load2之前执行。

StoreStore:保证store1保存在store2保存之前。

LoadStore:保证load1读取数据在store1写入数据之前。

StoreLoad:保证store保存数据在load读取数据之前。

JMM针对编译器制定的volatile重排序的规则表:

  • 当第一个操作为volatile读时,无论第二个操作是什么,都不能重排序。
  • 当第二个操作为volatile写时,无论第一个操作是什么,都不能重排。
  • 当第一个操作是volatile写时,第二个操作是读时,不能重排。

JMM在指令序列中插入屏障来禁止指令重排

  • 在volatile写操作的前面加StoreStore屏障
  • 在volatile写操作的后面加StoreLoad屏障
  • 在volatile读操作的后面加LoadLoad屏障
  • 在volatile读操作的后面加LoadStore屏障

volatile使用场景

单一赋值可以,复合赋值是禁止的。一般用来保存某个状态,判断业务是否结束。比如boolean值的flag。

总结

volatile可见性

volaile修饰的变量具有可见性。

对于写操作,本地内存中修改后,会立即刷回主存中。

对于读操作,本地内存会从主存中获取最新的值。

volatile有序性(禁止指令重排)

JMM在指令序列中通过插入内存屏障来禁止指令重排,保证有序性。

对于volatile写操作:在volatile写操作之前插入StoreStore指令,在volatile写操作之后插入StoreLoad指令来保证指令的有序。

对于volatile写操作:在volatile读操作之后插入LoadLoad指令和LoadStore指令,保证指令的有序。

参考:

1.《Java并发编程的艺术》

  1. JMM与volatile
相关推荐
阿维的博客日记21 天前
用volatile修饰数组代表什么意思,Java
java·juc·volatile
是三好1 个月前
并发容器(Collections)
java·多线程·juc
编程、小哥哥1 个月前
互联网大厂Java求职面试实录 —— 严肃面试官遇到搞笑水货程序员
java·面试·mybatis·dubbo·springboot·多线程·juc
yb0os11 个月前
手写一个简单的线程池
java·开发语言·数据库·计算机·线程池·juc
是三好1 个月前
Lock锁
java·juc
abc小陈先生1 个月前
JUC并发编程1
java·juc
左灯右行的爱情2 个月前
深入理解 G1 GC:已记忆集合(RSet)与收集集合(CSet)详解
java·jvm·后端·juc
左灯右行的爱情3 个月前
深入学习ReentrantLock
java·后端·juc
佛祖让我来巡山4 个月前
JUC相关知识点总结
juc
fly spider5 个月前
多线程-线程池的使用
java·面试·线程池·多线程·juc