为什么Java线程安全Singleton单例代码运行失败?双检锁实现问题咨询
问题解答
你当前写的带synchronized块的代码本身无法正常运行,因为第一次调用getInstance()方法时instance还是null,synchronized(null)会直接抛出空指针异常,这也是你删掉同步块、取消下方if判断注释后程序才能运行的核心原因。
你修改后的版本(无同步块、仅保留单层if判断)确实不满足线程安全要求,具体问题如下:
- 多线程并发调用
getInstance()时,可能有多个线程同时判断instance == null为真,会各自创建Singleton实例,最终出现多个实例,完全违背单例模式的核心要求。 - 没有同步机制的保护下,JVM的指令重排序可能会让其他线程拿到还未完成构造过程的半初始化
Singleton对象,引发未知的运行错误。
符合作业要求的双重检查锁定正确实现如下:
class Singleton { // volatile禁止指令重排,保证多线程下的可见性 volatile private static Singleton instance = null; private String someText; private Singleton() { this.someText = "Only one instance of this class can be created!"; } public static Singleton getInstance() { // 第一层检查:已经初始化的情况下直接返回,避免每次都抢锁 if (instance == null) { // 锁类对象而不是null的instance synchronized (Singleton.class) { // 第二层检查:抢到锁之后再判断一次,避免多线程同时过了第一层检查重复创建 if (instance == null) { instance = new Singleton(); } } } return instance; } public String getSomeText() { return this.someText; } public void setSomeText(String text) { this.someText = text; } } public class Assignment1 { public static void main(String[] args) { Singleton singleton1 = Singleton.getInstance(); Singleton singleton2 = Singleton.getInstance(); System.out.println(singleton1.getSomeText()); System.out.println(singleton2.getSomeText()); singleton1.setSomeText("Here's our new text!"); System.out.println(singleton1.getSomeText()); System.out.println(singleton2.getSomeText()); } }
这种实现既保证了线程安全,又避免了每次调用getInstance()都需要加锁的性能损耗,完全符合双重检查锁定的设计要求。
内容的提问来源于stack exchange,提问作者Mint
相关产品推荐
相关产品推荐

