volatile的实现简单概述

文章目录

  • 内存屏障
  • volatile关键字的实现
  • synchronized关键字的实现

内存屏障

在讲解是关键字之前,先来了解下内存屏障的概念。

处理器保障禁止内存重排序的指令被称为基本内存屏障。其作用是禁止该屏障前后之间的操作进行重排序,要确保指令前的操作要先于指令后的操作被提交。
读操作我们用Load表示;写操作我们用Store表示。

屏障名称 示例指令序列 具体作用
StoreLoad Store1;Store2; StoreLoad;Load1;Load2 保证该屏障前的任何一个写操作都会在该屏障后的任何一个读操作数据被加载之前同步到双方的高速缓存中。
StoreStore Store1;Store2;StoreSotre;Store3;Store4 保证该屏障前的任何一个写操作都会在该屏障后的任何一个写操作之前同步到双方的高速缓存中。
LoadLoad Load1;Load2;LoadLoad;Load3;Load4 保证该屏障前的任何一个读操作都会在该屏障后的任何一个读操作之前被加载
LoadStore Load1;Load2;LoadStore;Store1;Store2 保证该屏障前的任何一个读操作都会在该屏障后的任何一个写操作之前被同步双方高速缓存前被加载。

LoadLoad屏障和LoadStore屏障的组合称为获取屏障。它保障该屏障之前任何读操作于该屏障之后的任何读、写操作。
LoadStore屏障和StoreStore屏障的组合成称为释放屏障。它保证屏障之后的写操作于该屏障之前的任何读、写操作。

volatile关键字的实现

jvm在volatile变量读操作之前插入获取屏障。在volatile变量写操作前插入释放屏障。读线程和写线程通过各自执行的获取屏障和释放屏障保证了有序性。
volatile的实现简单概述_第1张图片

如上图,A、B是普通变量,V是用volatile修饰的变量,释放屏障保证了A、B的更新先于V更新提交,这保证了读线程在读取写线程对V的更新时也会读取到写线程对A、B变量的更新。
同时,jvm也会在读线程的volatile读操作后加上一个获取屏障,保证该线程对变量V的读取操作先于对A、B的读取操作。
注意:
屏障只能保证前、后之间的读取、写入顺序。屏障之前或者屏障之后的顺序并不会做保证。比如写线程可以先写入A再写入B,也可能先写入B再写入A,但肯定会先于V的写入。
除了保证有序性外,volatile还具有以下两个作用:

synchronized关键字的实现

jvm会在临界区开始前插入一个获取屏障,在临界区结束后插入一个释放屏障。
获取屏障保证读线程必须先获得锁之后才能进行临界区中的操作;释放屏障保证写线程在临界区中的读、写操作先临界区下面的写操作被提交。这就保证了有序性。

你可能感兴趣的:(jvm,java,数据结构)