线程安全的 3 种单例模式
举出 3 个线程安全的单例模式的实现,如下~
eg.1
通过JVM类的加载机制,Class 被类加载后,且在被线程使用之前,会执行类的初始化,而JVM会在初始化期间获取一个锁,该锁可以同步多个线程对同一个类的初始化。
1 public class Singleton { 2 3 /** 4 * 内部类 5 */ 6 private static class SingletonHandel { 7 static Singleton singleton = new Singleton(); 8 } 9 10 /** 11 * 获取对象 12 * 13 * @return 单实例对象 14 */ 15 public static Singleton getInstance() { 16 // 获取静态变量将导致 SingletonHandel 类初始化 17 // 类的初始化,JVM 保证有且仅有一个线程执行该类的初始化 18 return SingletonHandel.singleton; 19 } 20 21 }
eg.2
通过enum的本身特性,JVM 保障 每个枚举类型的单实例对象。
1 public class Singleton2 { 2 3 /** 4 * 获取对象 5 * 6 * @return 单实例对象 7 */ 8 public static Singleton2 getInstance() { 9 return SingletonEnum.INSTANCE.getInstance(); 10 } 11 12 private enum SingletonEnum { 13 /** 14 * 单实例对象 15 */ 16 INSTANCE(new Singleton2()); 17 18 /** 19 * 单例 20 */ 21 private Singleton2 singleton2; 22 23 SingletonEnum(Singleton2 singleton2) { 24 this.singleton2 = singleton2; 25 } 26 27 /** 28 * 获取单实例对象 29 * 30 * @return 单实例对象 31 */ 32 public Singleton2 getInstance() { 33 return singleton2; 34 } 35 } 36 }
eg.3
这里是对 双重检查锁定的优化,在 singleton3 = new Singleton3(); 这段代码这里,可能出现多线程竞争,所以必须使用 volatile 关键字。
1 public class Singleton3 { 2 3 private static volatile Singleton3 singleton3; 4 5 /** 6 * 获取单实例对象 7 * 8 * @return 单实例对象 9 */ 10 public static Singleton3 getInstance() { 11 // 优化双重检查锁定 12 if (null == singleton3) { 13 synchronized (Singleton3.class) { 14 if (null == singleton3) { 15 // + volatile 关键字 16 singleton3 = new Singleton3(); 17 } 18 } 19 } 20 return singleton3; 21 } 22 }

浙公网安备 33010602011771号