问题描述
从 Head First 设计模式一书中,具有双重检查锁定的单例模式已实现如下:
public class Singleton { private volatile static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
我不明白为什么要使用 volatile.volatile 的使用不会破坏使用双重检查锁定的目的,即性能吗?
推荐答案
了解为什么需要 volatile 的好资源来自 JCIP 书.Wikipedia 对此材料也有体面的解释.
真正的问题是 Thread A 可能在 instance 完成构造 instance 之前为其分配内存空间.Thread B 将看到该分配并尝试使用它.这会导致 Thread B 失败,因为它使用的是部分构造的 instance 版本.
问题描述
From Head First design patterns book, the singleton pattern with double checked locking has been implemented as below:
public class Singleton { private volatile static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
I don't understand why volatile is being used. Doesn't volatile usage defeat the purpose of using double checked locking i.e performance?
推荐答案
A good resource for understanding why volatile is needed comes from the JCIP book. Wikipedia has a decent explanation of that material as well.
The real problem is that Thread A may assign a memory space for instance before it is finished constructing instance. Thread B will see that assignment and try to use it. This results in Thread B failing because it is using a partially constructed version of instance.