如何写出线程安全的单例模式

本文详细探讨了四种常见的单例模式实现:懒汉模式的延迟加载、饿汉模式的初始化提前、静态内部类确保线程安全以及枚举类型的隐式锁定。重点讲解了多线程环境下 volatile 和类加载机制在保证线程一致性中的作用。
摘要由CSDN通过智能技术生成

对于单例模式就不做过多的介绍了,直接上代码

1.懒汉模式:延迟加载, 只有在真正使用的时候,才开始实例化

public class LazySingleton {

  private static volatile LazySingleton instance;

  private LazySingleton() {

  }

  public static LazySingleton getInstance() {
    if (instance == null) {
      synchronized (LazySingleton.class) {
        if (instance == null) {
          instance = new LazySingleton();
        }
      }
    }
    return instance;
  }
}

我们一个对象的创建过程分为三步

  1. 申请内存空间,进行空间分配。
  2. 将对象进行初始化。
  3. 将instance 指向刚分配的内存地址。

了解了上面一个对象的创建过程后,下面来看这样一个场景:
假设上面的instance变量没有被volatile修饰,在多线程环境下,有可能会出现这样的情况,为了达到性能最大化,CPU和JIT可能会对我们的指令进行重排,就可能出现下面的步骤,第三步在第二步之前执行,也就是:

  1. 申请内存空间,进行空间分配。
  2. 将instance 指向刚分配的内存地址。
  3. 将对象进行初始化。

那么,当后面的线程进来的时候发现instance 不为null(这里注意,虽然对象没被初始化,但是并不是null)直接返回,当使用时因为对象并没被初始化,便会出现问题。volatile在这里的作用就是保证多线程环境下代码执行的有序性。

2.饿汉模式:类加载的初始化阶段就完成了实例的初始化。

class HungrySingleton {

  private static HungrySingleton instance = new HungrySingleton();

  private HungrySingleton() {

  }

  public static HungrySingleton getInstance() {
    return instance;

  }

}

本质上就是借助于jvm类加载机制保证实例的唯一性及线程安全(JVM以同步的形式来完成类加载的整个过程)

3.静态内部类:本质上是利用类的加载机制来保证线程安全

class InnerClassSingleton {

  private static class InnerClassHolder {
    private static InnerClassSingleton instance = new InnerClassSingleton();
  }

  private InnerClassSingleton() {

    if (InnerClassHolder.instance != null) {
      throw new RuntimeException("Multiple instances are not allowed to be created");
    }
  }

  public static InnerClassSingleton getInstance() {
    return InnerClassHolder.instance;
  }
}

这里说一下构造器里面的判断是为了防止别人用反射的方式去获取实例,出现多实例的情况。

4…枚举类型

public enum EnumSingleton {
  INSTANCE;

  public void print() {
    System.out.println(this.hashCode());
  }
}

不支持反射创建对应的实例,且有自己的反序列化机制。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值