1. 五种单例实现逐一写出并分析并发与序列化安全性(含枚举单例)?
请写出五种单例实现,并逐一分析其并发与序列化安全性,其中包含枚举单例?
- 饿汉、懒汉、双重检查、静态内部类、枚举单例
- 并发安全性
- 序列化与反射破坏
五种单例实现:1)饿汉式:类加载时即创建实例,绝对线程安全,但可能造成不必要的实例化;2)懒汉式(synchronized 方法):线程安全但每次访问都加锁,性能差;3)双重检查锁(DCL):先判空再加锁再判空,volatile 保证实例可见性,兼顾性能与安全;4)静态内部类:利用类加载机制,JVM 保证类加载时静态内部类只初始化一次,天然线程安全且懒加载;5)枚举单例:JVM 保证枚举实例只创建一次,天然防序列化与反射破坏,最安全。饿汉与静态内部类靠 JVM 类加载保证安全;DCL 需 volatile;懒汉同步性能差;枚举兼顾序列化安全(JVM 特殊处理枚举序列化)与反射安全。
并发安全的核心是"实例只创建一次且可见"。枚举单例之所以最安全,是因为 JVM 对枚举有特殊保护:反射不能实例化枚举、序列化返回同一实例。DCL 必须用 volatile 防止指令重排导致拿到未初始化完成的实例。
// 饿汉
public class Singleton1 { private static final Singleton1 INSTANCE = new Singleton1(); private Singleton1(){} public static Singleton1 get(){return INSTANCE;} }
// 懒汉同步
public class Singleton2 { private static Singleton2 s; public static synchronized Singleton2 get(){ if(s==null) s=new Singleton2(); return s; } }
// 双重检查 DCL
public class Singleton3 { private static volatile Singleton3 s; public static Singleton3 get(){ if(s==null){ synchronized(Singleton3.class){ if(s==null) s=new Singleton3(); } } return s; } }
// 静态内部类
public class Singleton4 { private static class Holder{ static final Singleton4 I=new Singleton4(); } public static Singleton4 get(){ return Holder.I; } }
// 枚举单例
public enum Singleton5 { INSTANCE; public void doSomething(){} }