不利用锁写出4种安全的单例模式的方式

69 阅读1分钟

**主要从两个方面考虑这个问题

  1. 从无所编程的角度出发,利用CAS
  2. 利用JVM首次加载类的机制

1.利用静态变量初始化的饿汉式模式

public class singleton03 {

    private static singleton03 instance = new singleton03();

    private singleton03() {
    }

    public static singleton03 getInstance() {
        return instance;
    }

}

2.利用枚举

public enum Singleton7 {

    INSTANCE;
    

}
通过javap -c Singleton7.class 反编译字节码文件可以看到

public final class cn.roy.design.Singleton7 extends java.lang.Enum<cn.roy.design.Singleton7> {
  public static final cn.roy.design.Singleton7 INSTANCE;

  public static cn.roy.design.Singleton7[] values();
    Code:
       0: getstatic     #1                  // Field $VALUES:[Lcn/roy/design/Singleton7;
       3: invokevirtual #2                  // Method "[Lcn/roy/design/Singleton7;".clone:()Ljava/lang/Object;
       6: checkcast     #3                  // class "[Lcn/roy/design/Singleton7;"
       9: areturn

  public static cn.roy.design.Singleton7 valueOf(java.lang.String);
    Code:
       0: ldc           #4                  // class cn/roy/design/Singleton7
       2: aload_0
       3: invokestatic  #5                  // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
       6: checkcast     #4                  // class cn/roy/design/Singleton7
       9: areturn

  static {};
    Code:
       0: new           #4                  // class cn/roy/design/Singleton7
       3: dup
       4: ldc           #7                  // String INSTANCE
       6: iconst_0
       7: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
      10: putstatic     #9                  // Field INSTANCE:Lcn/roy/design/Singleton7;
      13: iconst_1
      14: anewarray     #4                  // class cn/roy/design/Singleton7
      17: dup
      18: iconst_0
      19: getstatic     #9                  // Field INSTANCE:Lcn/roy/design/Singleton7;
      22: aastore
      23: putstatic     #1                  // Field $VALUES:[Lcn/roy/design/Singleton7;
      26: return
}

本质就是饿汉式 + static代码块
  1. 利用CAS实现单例模式
public class Singleton06 {

    private static final AtomicReference<Singleton06> INSTANCE = new AtomicReference<Singleton06>();

    private static Singleton06 instance;

    private Singleton06() {
    }

    public static  Singleton06 getInstance() {
        for (; ; ) {
            Singleton06 instance = INSTANCE.get();
            if (null != instance){
                return instance;
            }
            INSTANCE.compareAndSet(null, new Singleton06());
            return INSTANCE.get();
        }
    }

}

4.利用静态内部类优化饿汉式

public class Singleton04 {

    private static class SingletonHolder {
        private static Singleton04 instance = new Singleton04();
    }

    private Singleton04() {
    }

    public static Singleton04 getInstance() {
        return SingletonHolder.instance;
    }

}