再探单例模式
一:故事背景
最近在进行单例模式的复习,今天进行一下对应的总结,分析一下各个设计模式。今天从最简单的单例模式开始。
二:单例重点
- 概念
一个类有且仅有一个实例,并且向整个系统提供这个实例。 - 分类
Java中有两种构建方式,分别是饿汉式和懒汉式。饿汉式的创建方式是私有的静态变量并且实例化,启动时就会创建。懒汉式有线程安全和线程不安全的两种。线程安全的可以通过加synchronized锁实现。 - 代码
这里我们重点分析懒汉模式的代码。
java
public class Singleton {
//1.私有的构造函数
private Singleton(){
}
//静态变量,防止指令重排序,不然的话可能将对象引用复制给了变量,但是却没有调用构造方法。
private static volatile Singleton singleton = null;
//对外提供访问点
public static Singleton getSingleton(){
//第一个if判断提高效率
if(singleton == null){
synchronized (Singleton.class){
//获取锁后判断,避免产生多个实例对象
if (singleton == null){
//这不是一个原子操作,先执行 = 在执行 new Singleton();
singleton = new Singleton();
}
}
}
return singleton;
}
}
- 重点
上述代码重点是两个,第一个是,为什么双重检验。判断单例对象是否为null 。第二个是为什么使用volatile 关键字,作用是什么 。
第一个问题,第一层的if判断是为了提升效率,并发获取对象,不用去竞争锁。第二个是避免,多个线程同时走到了synchronized 代码块这里,倒是创建重复的对象。
第二个问题的原因是通过使用volatile避免指令重排序。导致对象赋值给了singleton但是却没有执行构造函数,倒是出现错误。
三:总结提升
本文简单分析了单例模式,讲解了其中重点。