双重检查实现单例模式

双重检查设计模式用于减少synchronized的性能开销,延迟初始化单例对象。但仅使用synchronized无法防止重排序问题,可能导致线程看到未初始化的实例。通过使用volatile,确保变量对所有线程的可见性并禁止指令重排序,从而保证线程安全地初始化单例。

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

public class Singleton{
	private static volatile Singleton singleton;
	private Singleton(){}
	public Singleton getInstance(){
		if(singleton==null){
			synchronized(Singleton.class){
				if(singleton==null){
					singleton = new Singleton();
				}
			}
		}
		return singleton;
	}
}

第一次加锁是为了减少synchronized的开销,如果第一次检测的singleton不为null,则不需要进行加锁初始化操作,因此可以大幅度降低synchronized带来的性能开销。

第二次检测是为了延迟初始化,只有当使用到该对象的时候才进行初始化。

为什么要volatile呢?
synchronized虽然保证了原子性,但是却没有保证重排序的正确性,会出现A线程执行的过程中,先把引用地址发布,但是还未进行构造函数的情况,这是如果B线程来访问,他会看见已经赋值好的实例地址,但是内容却是空的。

而volatile可以保证线程的可见性,并且可以禁止指令重排序。就会解决这种情况。

  • 保证可见性,使用volatile定义的变量,将会保证对所有线程的可见性。
  • 禁止指令重排序优化,由于volatile禁止创建指令之间的重排序,所以其他线程不会访问正在初始化的对象,从而保证线程的安全性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值