java面试题之volatile的工作原理

volatile的特性:

  1. volatile可见性:对一个volatile的读,总可以看到对这个变量最终的写;
  2. volatile原子性:volatile对单个读/写具有原子性(32位Long、Double),但是复合操作除外,例如:i++;
  3. jvm底层采用“内存屏障”来实现volatile语义。

volatile的内存语义及实现:
  在JMM中,线程之间的通信采用共享内存来实现的。
volatile内存语义是:

  • 当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量值立即刷新到主内存中;
  • 当读一个volatile变量时,JMM会把该线程对应的本地内存设置为无效,直接从主内存中读取共享变量。


volatile的底层实现是通过插入内存屏障,但是对于编译器来说,发现一个最优布置来最小化插入内存屏障的总数几乎是不可能的,所以,JMM采用保守策略。如下:

  • 在每一个volatile写操作前面插入一个StoreStore屏障
  • 在每一个volatile写操作后面插入一个StoreLoad屏障
  • 在每一个volatile读操作后面插入一个LoadLoad屏障
  • 在每一个volatile读操作后面插入一个LoadStore屏障

StoreStore屏障可以保证在volatile写之前,其前面的所有普通写操作都已经刷新到主内存中;
StoreLoad屏障的作用是避免volatile写与后面可能有的volatile读/写操作重排序
LoadLoad屏障用来禁止处理器把上面的volatile读与下面的普通读重排序
LoadStore屏障用来禁止处理器把上面的volatile读与下面的普通写重排序

java中volatile关键字提供了一个功能,那就是被其修饰的变量在被修改后可以立即同步到主内存,被其修饰的变量在每次使用之前都从主内存刷新。因此,可以使用volatile来保证多线程操作时变量的可见性。

在java中,可以使用synchronized和volatile来保证多线程之间操作的有序性。实现方式有所区别:

  1. volatile关键字会禁止指令重排;
  2. 2、synchronized关键字保证同一时刻只允许一条线程操作。 synchronized是万能,他可以同时满足三种特性,这其实也是很多人滥用synchronized的原因。
posted @ 2018-11-20 17:47  胡金水  阅读(3987)  评论(0编辑  收藏  举报