单例模式 的 双重检查锁定 错在哪?

本文分析了Java多线程环境中,双重检查锁定(DoubleCheckedLocking)实现单例模式的错误根源,指出在特定情况下,由于指令重排序可能导致线程安全问题。即使在instance不为null时,对象仍可能未完成初始化,从而引发问题。文章探讨了这个问题发生的条件以及可能的解决方案。
摘要由CSDN通过智能技术生成

在Java多线程程序中,有时候需要采用延迟初始化来降低初始化类和创建对象的开销。双重检查锁定是常见的延迟初始化技术,但它是一个错误的用法。本文将分析双重检查锁定的错误根源 。

双重检查锁定的由来

在Java程序中,有时候可能需要推迟一些高开销的对象初始化操作,并且只有在使用这些对象时才进行初始化(单例)。此时程序员可能会采用延迟初始化。但要正确实现线程安全的延迟初始化需要一些技巧,否则很容易出现问题。

非线程安全实现:

public class UnsafeLazyInitialization {
    private static Instance instance;
    public static Instance getInstance() {
        if(instance == null) {                // 1:A线程执行
            instance = new Instance();        // 2:B线程执行
        }
        return instance;
    }
}

在UnsafeLazyInitialization类中,假设A线程执行代码1的同时,B线程执行代码2。此时,线程A可能会看到instance引用的对象还没有完成初始化 ( 原因在后边 )

线程安全的实现(低性能):

对于UnsafeLazyInitialization类中,我们可以对getInstance()方法做同步处理来实现线程安全的延迟初始化。示例代码如下。


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值