volatile原理(学习笔记)

Posted 唐 昊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了volatile原理(学习笔记)相关的知识,希望对你有一定的参考价值。

volatile原理

volatile 的底层实现原理是内存屏障,Memory Barrier(Memory Fence)

1. 对 volatile 变量的写指令后会加入写屏障

2. 对 volatile 变量的读指令前会加入读屏障

Double-checked locking (双重检查锁定)

为了提高性能,会延迟初始化某些类,在第一次使用的时候做类的初始化。为了保证多线程下的线程安全,一般会做安全同步。

//最开始的单例模式是这样的
    public final class Singleton 
        private Singleton()  
        private static Singleton INSTANCE = null;
        public static Singleton getInstance() 
        // 首次访问会同步,而之后的使用不用进入synchronized
        synchronized(Singleton.class) 
        	if (INSTANCE == null)  // t1
        		INSTANCE = new Singleton();
            
        
            return INSTANCE;
        
    
//但是上面的代码块的效率是有问题的,因为即使已经产生了单实例之后,之后调用了getInstance()方法之后还是会加锁,这会严重影响性能!因此就有了模式如下double-checked lockin:
    public final class Singleton 
        private Singleton()  
        private static Singleton INSTANCE = null;
        public static Singleton getInstance() 
            if(INSTANCE == null)  // t2
                // 首次访问会同步,而之后的使用没有 synchronized
                synchronized(Singleton.class) 
                    if (INSTANCE == null)  // t1
                        INSTANCE = new Singleton();
                    
                
            
            return INSTANCE;
        
    
//但是上面的if(INSTANCE == null)判断代码没有在同步代码块synchronized中,不能享有synchronized保证的原子性,可见性。所以

分析

以上的实现特点是

  1. 懒惰实例化
  2. 首次使用 getInstance() 才使用 synchronized 加锁,后续使用时无需加锁
  3. 第一个 if 使用了 INSTANCE 变量,是在同步块之外
  4. 但在多线程环境下,上面的代码是有问题的

比如

  1. 假设有两个线程A、B,当线程A 执行到 instance = new Singleton(); 时,线程B执行到 if (instance == null)。这里如果正常,那就是 Singleton被新建,并赋值给 instance ,线程B 拿到instance时不为null,同时开始使用 instance。

  2. 但是 instance = new Singleton();的执行过程可能被重排序。

正常过程:

  1. 分配内存空间
  2. 初始化Singleton实例
  3. 赋值 instance 实例引用

但是被重排序以后可能会出现:

  1. 分配内存空间
  2. 赋值 instance 实例引用
  3. 初始化Singleton实例

分析:

这样重排序并不影响单线程的执行结果,JVM是允许的。但是在多线程中就会出问题。

以上是关于volatile原理(学习笔记)的主要内容,如果未能解决你的问题,请参考以下文章

volatile学习笔记

内存屏障

JUC并发编程 原理之 volatile -- 保证可见性 & 保证有序性 & 习题 balking模式

内存屏障和volatile内存语义的实现

volatile 实现原理

内存屏障详解