Singleton 的双重检查锁定

简介: 【8月更文挑战第23天】

简介

Singleton 模式是一种设计模式,用于确保一个类只有一个实例。双重检查锁定是一种实现 Singleton 模式的常用技术,它利用了 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;
    }
}

工作原理

双重检查锁定利用了 Java 内存模型中的两个特性:

  • 原子性:volatile 字段的读写是原子的,这意味着它们不会被线程中断。
  • 可见性:volatile 字段的修改会立即对所有线程可见。

getInstance() 方法中,首先检查 instance 字段是否为 null。如果不是,则直接返回该实例。

如果 instancenull,则进入同步块。同步块确保只有单个线程可以同时访问此代码块。在同步块内,再次检查 instance 是否为 null。如果仍然为 null,则创建一个新的实例并将其分配给 instance 字段。

使用 volatile 关键字修饰 instance 字段非常重要。这确保了 instance 字段的修改对所有线程都是立即可见的。如果没有 volatile 关键字,则其他线程可能无法看到对 instance 的修改,从而导致多个实例的创建。

优点

  • 延迟加载:Singleton 实例仅在需要时才创建,这可以节省内存和性能。
  • 线程安全:同步块确保只有一个线程可以同时创建 Singleton 实例,从而保证了线程安全性。
  • 性能优化:与使用静态初始化器相比,双重检查锁定可以减少同步开销,从而提高性能。

缺点

  • 复杂性:双重检查锁定的实现比使用静态初始化器更复杂。
  • 潜在的性能问题:如果多个线程同时访问 getInstance() 方法,则可能导致过多的同步开销,从而影响性能。

最佳实践

  • 仅在确实需要 Singleton 模式时才使用它。
  • 优先考虑使用枚举来实现 Singleton,因为它更简单、更安全。
  • 如果使用双重检查锁定,请确保 instance 字段是 volatile 的。
  • 考虑使用静态内部类来实现 Singleton,它可以提供类似的优点,但更简单。

替代方案

除了双重检查锁定之外,还有其他实现 Singleton 模式的技术,包括:

  • 静态初始化器:这是最简单的实现,但它不是线程安全的。
  • 枚举:枚举是实现 Singleton 的一种简单且线程安全的方法。
  • 静态内部类:这是一种线程安全且延迟加载的实现。

总结

双重检查锁定是一种实现 Singleton 模式的常用技术,它提供了延迟加载、线程安全性和良好的性能。但是,它比其他技术更复杂,并且在高并发场景中可能会遇到性能问题。在选择 Singleton 实现时,应根据具体需求权衡优点和缺点。

目录
相关文章
|
设计模式 存储
static应用之 单例设计模式(饿汉单例&懒汉单例)
本章我们来学习单例模式中的饿汉单例和懒汉单例,那么什么是单例模式呢?应用该模式的这个类永远只有一个实列,即一个类只能创建一个对象例如电脑上的任务管理器对象只需要一个就能解决问题,可以节省内存空间先定义一个类,把构造器私有如下图,先来看一下没有把构造器私有化的SingleInstance类,此时Test类中可以随意创建多个SingleInstance的实例化。 在SingleInstance类中用private修饰无参构造器,此时左边new方法报错了。我们在右边创建一个静态变量来存储对象,变量名为instan
52 0
|
6月前
|
设计模式 安全 Java
单例模式:饿汉模式、懒汉模式
单例模式:饿汉模式、懒汉模式
88 0
|
5月前
|
安全 Java
线程安全的单例模式(Singleton)
线程安全的单例模式(Singleton)
|
6月前
|
SQL 安全 Java
懒汉式单例的3个坑
懒汉式单例的3个坑
|
6月前
|
安全 Java 编译器
单例模式之饿汉模式&懒汉模式
单例模式之饿汉模式&懒汉模式
|
缓存 安全 Java
双重检查锁单例
双重检查锁单例
|
安全 Java
懒汉式单例
懒汉式单例
|
安全 C#
单例模式(Singleton)
单例模式(Singleton)
67 0
@Singleton和@ApplicationScoped的区别
在JakartaEE的CDI标准中@Singleton和@ApplicationScoped的区别
399 0
|
设计模式 存储 安全