单例模式是一种常用的软件设计模式,它保证一个类只有一个实例,并提供一个全局访问点,在多线程环境中,确保单例的线程安全是非常重要的,下面是一个线程安全的单例模式实现的示例代码及其测试方法。
实现线程安全的单例模式
懒汉式,双重检查锁定(DCL, Double-Checked Locking)
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; } }
测试单例模式的线程安全
为了验证单例模式是否线程安全,我们可以创建多个线程同时尝试获取单例实例,并检查所有线程返回的是否是相同的实例。
单元测试
测试用例 | 描述 | 预期结果 |
Test 1 | 多线程同时调用getInstance()方法 | 所有线程获得相同的实例 |
代码:
public class SingletonTest { public static void main(String[] args) { Runnable test = () -> { Singleton singleton = Singleton.getInstance(); System.out.println(singleton); }; Thread t1 = new Thread(test); Thread t2 = new Thread(test); // ... 可以创建更多线程进行测试 t1.start(); t2.start(); // ... 启动所有线程 } }
在上述测试中,我们创建了多个线程并同时执行Singleton.getInstance()
,预期输出应该是所有线程打印出相同的实例地址,这表示单例模式是线程安全的。
相关问题与解答
Q1: 为什么需要在单例模式中使用两次null检查?
A1: 在多线程环境中,双重检查锁定(DCL)用于减少同步开销,第一次检查是为了不必要的同步开销,如果实例已经被创建,直接返回即可,第二次检查是在同步块内进行的,确保在当前线程进入同步块之前没有其他线程已经创建了实例。
Q2: volatile关键字在单例模式中有什么作用?
A2:volatile
关键字确保了变量的可见性,当一个线程修改了一个volatile
变量的值,新值马上对其他线程变得可见,在单例模式中,它确保了当instance
被初始化成一个新的Singleton实例时,这个变化对其他线程立即可见,防止了使用尚未完全创建的对象。
原创文章,作者:未希,如若转载,请注明出处:https://www.kdun.com/ask/1033914.html
本网站发布或转载的文章及图片均来自网络,其原创性以及文中表达的观点和判断不代表本网站。如有问题,请联系客服处理。
发表回复