Hongwei's Diary
Fork me on GitHub

双重锁单例模式笔记

2019-01-10

本文介绍了双重锁的单例模式实现方式和部分问题解答(有道云笔记迁移)

一、代码实现

/**
* @Description 双重锁单例模式
* @Author hw
* @Date 2019/1/10 16:27
* @Version 1.0
*/
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;
}
}

编译后的字节码指令

10: monitorenter
11: getstatic #2 // Field singleTon:LSingleTon;
14: ifnonnull 27
17: new #3 // class SingleTon
20: dup
21: invokespecial #4 // Method "<init>":()V
24: putstatic #2 // Field singleTon:LSingleTon;
27: aload_0
28: monitorexit

二、为什么需要volatile?

1. 禁止指令重排序(有序性)

实例化一个对象其实可以分为三个步骤:  

  1. 分配内存空间。  
  2. 初始化对象。  
  3. 将内存空间的地址赋值给对应的引用。

但是由于操作系统可以对指令进行重排序,所以上面的过程也可能会变成如下过程:  

  1. 分配内存空间。  
  2. 将内存空间的地址赋值给对应的引用。  
  3. 初始化对象

2. 保证singleTon对象的可见性

三、如果synchronized里面不加if判断会发生什么?

多个线程竞争synchronize锁,只有一个拿到,剩下的会在锁释放的时候再次进行new 操作,就会导致执行多次,出现多个实例。

使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏

扫描二维码,分享此文章