作为被面试官最喜欢问到的23种设计模式之一,我们不得不熟练掌握单例模式以及洞悉多线程环境下,单例模式所存在的非线程安全问题以及它的解决方式。
注:这篇文章主要讲述多线程环境下单例模式存在的非线程安全问题,并不详细讲述单例模式。
1 何为单例模式
首先大概了解一下单例模式的定义:
- 单例类只能有一个实例。
- 单例类必须自己创建自己的唯一实例。
- 单例类必须给所有其他对象提供这一实例。
单例模式的应用非常广泛,例如在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。选择单例模式就是为了避免不一致状态。
单例模式的实现有三种方式:饿汉式(天生线程安全),懒汉式,登记式(可忽略)。
对于上面单例模式的实现方式在这里不做过多介绍,我们着重来看一下懒汉式在多线程环境下出现的问题以及它的解决策略。
2 设计线程安全的单例模式
2.1 DCL双检查锁机制
能看这篇文章的伙伴对设计线程安全的单例模式应该都有一定的了解,所以对于解决非线程安全的单例模式的3种方式也应该有些了解。我们再来总结一下这三种方式:声明synchronized关键字(同步代码块),DCL双检查锁机制,静态内置类的实现。
关于第一种方式,不再讲述,这里主要关注DCL双检查锁机制。
这是单例类,注意 private volatile static MyObject myObject
。
public class MyObject {
private volatile static MyObject myObject;
private MyObject() {
}
public static MyObject getInstance() {
try {