package com.yunding.concurrent;
/**
* 多线程环境下的单例模式: doubleChecked + volatile (双重检测 + 避免happenBefore)
*
* 实例化对象的三个步骤: 1. 开辟空间 2. 初始化对象 3. 把对象的地址赋给引用变量
*
* @author beOkWithAnything
*
*/
public class DoubleCheckedLocking {
/**
* 3. 提供 volatile修饰的 私有的静态属性 DoubleChecking 可能会存在指令重排(happenBefore):
* 如果初始化操作比较耗时,可能会发生指令重排:对象未初始化完成就把对象的地址赋给引用变量
* 由于存在DoubleChecking,新的线程就会访问到未初始化完成的对象,加入volatile来避免指令重排(保证对象使用时内容同步更新)
*/
private static volatile DoubleCheckedLocking instance;
// 构造器私有化
private DoubleCheckedLocking() {
}
// 提供公共的静态方法: 获取属性
public static DoubleCheckedLocking getInstance() {
/**
* 2. 已经存在对象时: 避免不必要的同步
* 如果没有双重检测(DoubleChecked),每个线程都要去等待当前持有instance锁的线程判断完成才能返回实例
*/
if (null != instance) {
return instance;
}
/**
* 1. 加锁: 如果初始化对象的步骤比较耗时,多线程环境下不加锁会 重复创建对象
*/
synchronized (instance) {
if (null == instance) {
instance = new DoubleCheckedLocking();
}
}
return instance;
}
}