DCL单例模式详解

本文深入解析DCL单例模式,即双重检查锁定在单例模式中的应用,重点介绍了其线程安全性与效率优势。从私有构造函数、同步代码块到volatile关键字的使用,全面阐述了DCL模式如何防止多线程环境下实例的重复创建。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

public class SingleInstance {
	private volatile static SingleInstance instance;

	private SingleInstance() {

	}

	public static SingleInstance getInstance() {
		if (instance == null) {
			synchronized (SingleInstance.class) {
				if (instance == null) {
					instance = new SingleInstance();
				}
			}
		}
		return instance;
	}
}

DCL单例模式中的DCL为Double Check Lock缩写,即双重检查锁定,是单例模式中线程安全的懒汉式单例模式,下面我们来分析一下这种单例模式的意义何在。


第一步:使用私有的构造函数,单例模式常规写法,防止外部通过构造方法初始化,统一初始化入口。


第二步:同步代码块外加判空条件,这个判空是为了程序效率,全掉后导致效率变低。因为去掉之后,不管instance是否已经初始化,都会进行synchronized操作,而synchronized是一个重操作消耗性能。加上之后,如果已经初始化直接返回结果,不会进行synchronized操作。


第三步:初始化实例代码加上synchronized是为了防止多个线程同时调用getInstance方法时,各初始化instance一遍的并发问题。


第四步:同步代码块里加判空条件,为了防止多线程情况下多次初始化实例,假设两个线程a和b都通过了第一个判空条件。此时假设a先获得锁,进入synchronized的代码块,初始化instance,a释放锁。接着b获得锁,进入synchronized的代码块,也直接初始化instance,导致初始化了两次,加上判空就可以防止这种情况发生


一个注意点:instance的声明有一个voliate关键字,如果不用该关键字,有可能会出现异常。因为instance = new SingleInstance();并不是一个原子操作,会被编译成三条指令,如下所示。

java会指令重排序,也就是说jvm执行上面三条指令的时候,不一定是1-2-3这样执行,有可能是1-3-2这样执行。如下图,Thread1执行到16行指令,此时并没有将实例初始化,同时Thread2执行到11行判空的时候发现为false,因为instance指向了S内存,就直接返回了instance实例,但此时instance并没有初始化完全所以上层在使用的时候会出现问题

我们给instance变量加上volatile关键字,就禁止了jvm的指令重排,那指令就是1-2-3的去执行,此时便不会有问题。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值