opoojkk

几种单例的比较

xx
目次

懒汉式 #

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// java
public class Singleton {
    private static final Singleton INSTANCE = new Singleton();
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        return INSTANCE;
    }
}
1
2
// kotlin
object KotlinSingleton {}

优势:

  1. 实现简单;
  2. 没有同步开销;

不足:

  1. 类加载时创建,可能造成资源浪费;

线程安全:

JVM保障(静态变量只在加载时创建一次)。

饿汉式 #

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// java
public class Singleton {
    private static Singleton instance;
    
    private Singleton() {}
    
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
1
2
3
4
5
6
7
8
// kotlin
class LazySingleton private constructor() {
    companion object {
        val instance: LazySingleton by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
            LazySingleton()
        }
    }
}

优势:

  1. 减少了不必要的资源浪费

不足:

  1. 首次访问有同步开销

线程安全:

需要依赖同步锁实现线程安全。

双重检查式 #

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// java
public class Singleton {
    private static volatile Singleton instance;
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        if (instance == null) {  // 第一次检查
            synchronized (Singleton.class) {
                if (instance == null) {  // 第二次检查
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// kotlin
class Singleton private constructor() {
    
    companion object {
        // 使用 @Volatile 注解确保可见性和禁止指令重排序
        @Volatile
        private var instance: Singleton? = null
        
        fun getInstance(): Singleton {
            // 第一次检查:避免不必要的同步
            return instance ?: synchronized(this) {
                // 第二次检查:防止多个线程同时通过第一次检查后重复创建
                instance ?: Singleton().also { 
                    instance = it 
                }
            }
        }
    }
}

优势:

  1. 延迟加载
  2. 只有第一次访问时有同步开销

不足:

  1. 实现复杂

线程安全:

volatile防止指令重排序。

静态内部类 #

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// java
public class Singleton {
    private Singleton() {}
    
    private static class Holder {
        static final Singleton INSTANCE = new Singleton();
    }
    
    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// kotlin
class Singleton private constructor() {
 
    // 伴生对象作为静态成员的容器
    companion object {
        // 使用属性访问器实现延迟初始化
        val instance: Singleton by lazy { Holder.INSTANCE }
    }
 
    // 私有静态内部类(Holder模式)
    private object Holder {
        // 由 JVM 保证线程安全的初始化
        val INSTANCE = Singleton()
    }
}

优势:

  1. 实现简单
  2. 没有同步开销

不足:

  1. 无法初始化参数

线程安全:

JVM保障,同饿汉式。

枚举单例 #

1
2
3
4
5
public enum EnumSingleton {
    INSTANCE;
    
    public void doSomething() { ... }
}

优势:

  1. 方式反射、序列化破坏单例;

不足:

  1. 可嫩造成不必要的资源浪费;

线程安全:

由JVM保证(类似静态单例初始化)。

总结 #

类型实现方式语言线程安全初始化时机优势不足线程安全保证机制
非懒加载饿汉式Java类加载时实现简单,无同步开销可能造成资源浪费JVM类加载机制
枚举单例Java类加载时绝对防止反射/序列化破坏不够灵活JVM枚举特性保证
Object声明Kotlin首次访问类时语法级支持,简洁安全非严格懒加载编译器生成静态内部类
懒加载同步方法Java首次调用时延迟加载节省资源每次调用都同步,性能差synchronized方法锁
双重检查锁(DCL)Java首次调用时高性能(仅首次同步)实现复杂,需volatilevolatile+同步块禁止指令重排
静态内部类Java首次调用时无同步开销,优雅实现无法传递初始化参数JVM类加载机制
lazy(SYNCHRONIZED)Kotlin首次属性访问时灵活控制初始化时机首次访问有同步开销委托内部使用同步锁
lazy(PUBLICATION)Kotlin⚠️有条件首次属性访问时允许多线程并行初始化可能多次初始化CAS操作保证最终一致性
lazy(NONE)Kotlin首次属性访问时完全无同步开销仅限单线程环境无保护机制
标签:
Categories: