面试官:单例模式静态内部类为什么线程安全?

本文解析了静态内部类单例模式为何在多线程环境下是线程安全的,通过JVM初始化锁机制确保类只初始化一次,并解释了阻塞和唤醒原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

最近面试一家外企,面试官问我为什么静态内部类单例模式是线程安全的?

按我的理解,应该是类初始化的时候,维护了一个static boolean类型的变量,用来表示类有没有被初始化过,类初始化的时候会判断这个变量进而决定是否初始化。面试官也没说什么,但我总感觉少了点什么。于是查阅资料、记录一下。

代码样例

public class StaticInnerClassSingleton {
    private StaticInnerClassSingleton() {

    }

    public static StaticInnerClassSingleton getSingleton() {
        return SingletonHolder.singleton;
    }

    private static class SingletonHolder {
        private static final StaticInnerClassSingleton singleton = new StaticInnerClassSingleton();
    }
}

参考回答

  • 我们在静态内部类中使用饿汉式方式创建了一个静态常量/变量。
  • JVM保证对于每一个类或接口C,都有一个唯一的初始化锁LC与之对应;保证一个类的类构造器在多线程环境中被正确的加锁、同步。
    • 如果多个线程同时去初始化一个类,那么只有一个线程能获取到初始化锁LC去执行这个类的类构造器
    • 其他的线程都需要阻塞等待,直到活动线程执行<clinit>()方法完毕。
    • 并且每个线程至少获取一次初始化锁LC来确保这个类已经被初始化过了。
  • 所以在同一个类加载器下,一个类只会被初始化一次。
  • 而静态属性保证了全局唯一,静态变量初始化保证了线程安全。

注:

  • 一个线程执行类初始化操作,其他线程虽然会被阻塞,但是执行类初始化的线程退出后,其他线程在被唤醒之后不会进入/执行<clinit>()方法。
  • 如果一个类初始化特别慢,就可能造成其他线程阻塞很久,而这种阻塞往往在实际应用中是隐藏的。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秃秃爱健身

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值