单例模式双重校验_您真的懂单例吗:程序员必须掌握的设计模式之单例模式

本文探讨了单例模式的核心概念,包括为何使用、不同场景下的保证方法(同步锁、反射、反序列化、克隆),并详细介绍了6种常见实现方式及其优缺点。特别关注Spring和非Spring环境下的推荐策略,以及如何避免反射、序列化和克隆破坏单例。

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

7d9b8a06937fbc4485c5fe6d61bc6e5a.png

一、什么是单例模式

对象在系统中只存在一个实例,称为单例(Singleton)。反之,存在多个实例的,叫多例。虽然是设计模式中最简单的模式,但是很多同学却没有深入了解它,如果面试的时候问到这个问题,您能过关吗?(以下代码示例都采用Java语言)

二、为什么要使用单例模式

可以节省内存,保证对象数据的一致性。例如,配置类,系统中只要存在一个实例即可,多个实例既没必要也难维护。

三、如何实现单例模式

1、保证多线程单例

在多线程场景下,也要保证只有一个实例。常规方法是加同步锁。

2、保证特殊创建对象场景下的单例

常用的创建对象的方法有构造器和静态工厂,而特殊的创建对象方法还有反射、反序列化和克隆。我们必须保证特殊场景下也是单例的。

  • 保证反射单例

由于通过反射机制,可以调用私有构造器,所以,存在多个实例的可能,保证反射下也能单例的方法是,在构造器中抛出异常:

f0bd8388719b93002756fba6fca65df8.png

图1 保证反射单例示例代码

  • 保证反序列化单例

一个类如果实现了 java.io.Serializable接口,它就有可能被序列化和反序列化。在反序列化的时候,要保证单例,必须重写readResolve方法:

f646453d103f781d445207a872836b5b.png

图2 保证反序列化单例示例代码

  • 保证克隆单例

在克隆场景下,要保证单例,我们必须让对象不能实现cloneable接口。也就是让它无法克隆。

3、常规的6种实现方式(都支持线程安全)

  • 饿汉式

该方式指类一加载就创建一个实例:

e18c1c86bfb8b81e6a935264f573c9da.png

图3 饿汉式示例代码

  • 懒汉式

延迟创建实例,需要时再加载,由于有同步操作,会有性能问题:

e00ef7fc68db274d7957c20455497dbe.png

图4 懒汉式示例代码

  • 双重校验锁

解决同步操作每次都要等待同步锁,导致性能降低的问题。使用volatile禁止指令重排,避免了指令重排导致的线程安全问题:

6225cb3ea7f0a1725e8905a1435f4b27.png

图5 双重校验锁示例代码

  • 静态内部类

在静态内部类里面创建单例,由于静态内部类在初始化的时候会获得初始化锁,所以是线程安全的,不再需要同步操作,避免了性能问题:

1552fb2c649f069cb7dec6f987bfc38c.png

图6 静态内部类示例代码

  • 枚举

通过枚举来实现单例:

e72ffd7b66597ee8c6c239292810668f.png

图7 枚举示例代码

  • 注册登记式

每次初始化对象,都往固定的容器中去注册一下并进行缓存,下次使用的时候去缓存中读取:

92e08f57f5b17b65fe44ac5e77eebf28.png

图8 注册登记式示例代码

如果上述所示,通过getBean方法去获取类的实例。

四、实现方式对比

我们来对比一下上述6种实现方式,对比维度是:是否支持懒加载、是否支持反射单例、是否支持反序列化单例、是否支持克隆单例、是否没有性能问题。

918e8b0906ca98a21a030e47147e6e4d.png

图9 实现方式对比表

五、结论

在Spring环境下,我们推荐使用注册登记式,因为这本来就是Spring容器自带的实现方式。

非Spring环境下,推荐使用枚举方式。如果枚举不能用,比如单例模式类需要使用继承,推荐使用静态内部类或者双重校验锁。

除了枚举方式,其他方式都要注意反射、反序列化和克隆场景下的破坏单例问题。

e9e77e843e012a2f0e442554a7e53124.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值