Junhc

岂止于博客

设计模式之单例模式

基于volatile的解决方案
public class SafeDoubleCheckedLocking {

  private volatile static Instance instance;

  public static Instance getInstance() {
    if(instance == null) {
      synchronized(SafeDoubleCheckedLocking.class) {
        if(instance == null) {
          // 1.分配对象的内存空间
          // 2.初始化对象
          // 3.设置 instance 指向刚分配的内存地址
          // 如果 instance 不使用 volatile 修饰,那么23指令重排
          // 多线程并发情况下,线程将会访问到一个还未初始化的对象
          instance = new Instance();
        }
      }
    }
  }

}
基于类初始化的解决方案

JVM在类的初始化阶段(即在Class被加载后,且被线程使用之前),会执行类的初始化。
在执行类的初始化期间,JVM会去获取一个锁。

public class InstanceFactory {

  private static class InstanceHolder {
    public static Instance instance = new Instance();
  }

  public static Instance getInstance() {
    return InstanceHolder.instance; // 这里将导致 InstanceHolder 类被初始化
  }

}

Java语言规范,在首次发生下列任意一种情况时,一个类或接口类型T将被立即初始化。
1) T是一个类,且一个T类型的实例被创建
2) T是一个类,且T中声明的一个静态方法被调用
3) T中声明的一个静态字段被赋值
4) T中声明的一个静态字段被使用,且这个字段不是一个常量字段
5) T是一个顶级类,且一个断言语句嵌套在T内被执行