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保证的原子性,可见性。所以
分析
以上的实现特点是:
- 懒惰实例化
- 首次使用 getInstance() 才使用 synchronized 加锁,后续使用时无需加锁
- 第一个 if 使用了 INSTANCE 变量,是在同步块之外
- 但在多线程环境下,上面的代码是有问题的
比如:
-
假设有两个线程A、B,当线程A 执行到 instance = new Singleton(); 时,线程B执行到 if (instance == null)。这里如果正常,那就是 Singleton被新建,并赋值给 instance ,线程B 拿到instance时不为null,同时开始使用 instance。
-
但是 instance = new Singleton();的执行过程可能被重排序。
正常过程:
- 分配内存空间
- 初始化Singleton实例
- 赋值 instance 实例引用
但是被重排序以后可能会出现:
- 分配内存空间
- 赋值 instance 实例引用
- 初始化Singleton实例
分析:
这样重排序并不影响单线程的执行结果,JVM是允许的。但是在多线程中就会出问题。
以上是关于volatile原理(学习笔记)的主要内容,如果未能解决你的问题,请参考以下文章