Java单例模式如何线程安全

wen java案例 1

本文目录导读:

Java单例模式如何线程安全

  1. 饿汉式(推荐,简单安全)
  2. 懒汉式(双重检查锁定 - DCL)
  3. 静态内部类(推荐,懒加载)
  4. 枚举实现(最安全)
  5. CAS实现(无锁)

Java中实现线程安全的单例模式有多种方式,以下是几种主流且可靠的方法:

饿汉式(推荐,简单安全)

public class Singleton {
    // 类加载时即创建实例,JVM保证线程安全
    private static final Singleton INSTANCE = new Singleton();
    private Singleton() {}
    public static Singleton getInstance() {
        return INSTANCE;
    }
}

优点:实现简单,天然线程安全
缺点:类加载时就创建实例,可能造成资源浪费

懒汉式(双重检查锁定 - DCL)

public class Singleton {
    // volatile关键字禁止指令重排序,保证可见性
    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;
    }
}

注意:必须使用volatile关键字,否则可能因指令重排序导致返回未初始化完成的实例

静态内部类(推荐,懒加载)

public class Singleton {
    private Singleton() {}
    // JVM保证类的初始化是线程安全的
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

优点

  • 懒加载:只有调用getInstance()时才加载内部类
  • 线程安全:由JVM类加载机制保证
  • 实现简洁,无同步开销

枚举实现(最安全)

public enum Singleton {
    INSTANCE;
    // 可以添加其他方法
    public void doSomething() {
        // ...
    }
}

优点

  • 绝对防止反序列化创建新实例
  • 防止反射攻击
  • 实现最简单,线程安全

CAS实现(无锁)

import java.util.concurrent.atomic.AtomicReference;
public class Singleton {
    private static final AtomicReference<Singleton> INSTANCE = new AtomicReference<>();
    private Singleton() {}
    public static Singleton getInstance() {
        for (;;) {
            Singleton instance = INSTANCE.get();
            if (instance != null) {
                return instance;
            }
            instance = new Singleton();
            if (INSTANCE.compareAndSet(null, instance)) {
                return instance;
            }
        }
    }
}
方法 懒加载 性能 防止反射 防止序列化 推荐度
饿汉式
DCL
静态内部类
枚举
CAS

推荐选择

  • 无特殊需求:使用静态内部类方式
  • 需要防止反射/序列化:使用枚举方式
  • 简单场景:使用饿汉式

这些方法都能确保线程安全,选择哪种取决于具体需求和约束条件。

抱歉,评论功能暂时关闭!