你应该知道的 volatile 关键字(下)

简介: 不管是在面试还是实际开发中 volatile 都是一个应该掌握的技能。 首先来看看为什么会出现这个关键字。

指令重排


内存可见性只是 volatile 的其中一个语义,它还可以防止 JVM 进行指令重排优化。

举一个伪代码:


int a=10 ;//1
int b=20 ;//2
int c= a+b ;//3


一段特别简单的代码,理想情况下它的执行顺序是:1>2>3。但有可能经过 JVM 优化之后的执行顺序变为了 2>1>3


可以发现不管 JVM 怎么优化,前提都是保证单线程中最终结果不变的情况下进行的。

可能这里还看不出有什么问题,那看下一段伪代码:


private static Map<String,String> value ;
private static volatile boolean flag = fasle ;
//以下方法发生在线程 A 中 初始化 Map
public void initMap(){
  //耗时操作
  value = getMapValue() ;//1
  flag = true ;//2
}
//发生在线程 B中 等到 Map 初始化成功进行其他操作
public void doSomeThing(){
  while(!flag){
    sleep() ;
  }
  //dosomething
  doSomeThing(value);
}


这里就能看出问题了,当 flag 没有被 volatile 修饰时,JVM 对 1 和 2 进行重排,导致 value 都还没有被初始化就有可能被线程 B 使用了。


所以加上 volatile 之后可以防止这样的重排优化,保证业务的正确性。


指令重排的的应用


一个经典的使用场景就是双重懒加载的单例模式了:


public class Singleton {
    private static volatile Singleton singleton;
    private Singleton() {
    }
    public static Singleton getInstance() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    //防止指令重排
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}


这里的 volatile 关键字主要是为了防止指令重排。


如果不用 ,singleton = new Singleton();,这段代码其实是分为三步:


  • 分配内存空间。(1)


  • 初始化对象。(2)


  • singleton 对象指向分配的内存地址。(3)


加上 volatile 是为了让以上的三步操作顺序执行,反之有可能第二步在第三步之前被执行就有可能某个线程拿到的单例对象是还没有初始化的,以致于报错。


总结


volatileJava 并发中用的很多,比如像 Atomic 包中的 value、以及 AbstractQueuedLongSynchronizer 中的 state 都是被定义为 volatile 来用于保证内存可见性。


将这块理解透彻对我们编写并发程序时可以提供很大帮助。


相关文章
|
2月前
|
缓存 编译器
volatile关键字
volatile关键字
|
4月前
|
缓存 编译器 C语言
一起来探讨volatile关键字
在C语言中,volatile是一个关键字,用于告诉编译器不要对被声明为volatile的变量做优化,以确保每次对该变量的读写都直接操作内存。
|
7月前
|
缓存 安全 Java
【volatile关键字】
【volatile关键字】
|
存储 Java
浅谈Volatile关键字
该篇文章用来总结笔者对于Volatile关键字的理解,并不会太过深入的探讨。
103 0
浅谈Volatile关键字
|
SQL 缓存 Java
Volatile关键字介绍
Volatile关键字介绍
Volatile关键字介绍
|
存储 缓存 Java
volatile关键字再理解
volatile关键字再理解
volatile关键字再理解
|
缓存 前端开发 Java
volatile关键字有什么用?
volatile关键字有什么用?
volatile关键字有什么用?
|
缓存 安全 算法
你应该知道的 volatile 关键字(上)
不管是在面试还是实际开发中 volatile 都是一个应该掌握的技能。 首先来看看为什么会出现这个关键字。
|
SQL 缓存 安全
volatile 关键字详解(下)
本文主要是讲解 volatile 关键字的使用,首概括它的三大特征,然后引入 JMM 模型,结尾我们解释了单例模式(懒汉模式)中为什么要用 volatile。
135 0
volatile 关键字详解(下)
|
存储 安全 Java
volatile 关键字详解(上)
本文主要是讲解 volatile 关键字的使用,首概括它的三大特征,然后引入 JMM 模型,结尾我们解释了单例模式(懒汉模式)中为什么要用 volatile。
131 0
volatile 关键字详解(上)