懒汉设计模式
代码
class Singleton {
volatile private static Singleton instance = null;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
}
private Singleton() {
}
}
为什么使用 volatile 和两个 if 判断?
- 内层加锁判断:在内层中加了
synchronized
锁判断 if (instance == null)
,是为了 防止 两个线程在同一时间调用 getInstance()
, 然后判断结果为实例都为 null,从而导致两个线程都创建了实例; - 外层判断:而外层
if (instance == null)
则是防止之后其他线程创建连接都需要加锁进行判断,线程之间的执行方式变成了串行, 时间效率大大变低。因此直接先判断 instance == null ,如果不等于 null,也就说之前已经创建过了实例,那么 直接返回实例 - 加 volatile 关键字:根据 2. 外层判断 中得知,如果开始有线程创建实例后,那么后续的线程只需要判断第一层循环即可,因为开始有线程已经把 instance 实例对象写入到内存了。
但是还是存在一个问题,如果后续线程在 cpu 执行的时候,直接到 cpu 的寄存器查找 instance
,判断其是否为 null
,发现还是 null
,那么就进入内层判断(当然,进入内层的判断是 synchronized 修饰的,已经保证了内存的可见性,因此不会创建新的 instance 实例),这就是内存可见性的问题。因此需要在 instance
对象前加 volatile
关键字保证内存可见性!