为什么要使用双重检查锁定
Why use double checked locking
关于我提出的 ,
public static Singleton getInstanceDC() {
if (_instance == null) { // Single Checked (1)
synchronized (Singleton.class) {
if (_instance == null) { // Double checked (2)
_instance = new Singleton();
}
}
}
return _instance;
}
为什么要使用第二个实例空检查条件。它可能有什么影响?
让我们对行进行编号,以便了解线程如何交错操作。
if (_instance == null) { // L1
synchronized (Singleton.class) { // L2
if (_instance == null) { // L3
_instance = new Singleton();// L4
}
}
}
让我们考虑一个不检查 L3 的交错。
- 线程 1 到达 L1 且
_instance
为 null
- 线程 2 到达 L1 且
_instance
为 null
- 线程 1 在 L2 获得互斥
- 线程 2 尝试在 L2 处获取互斥量但阻塞
- 线程 1 创建新实例并在 L4 分配
- 线程 1 从 L2 释放互斥量
- 线程 2 在 L2 获得互斥
- 线程 2 创建新实例并在 L4 分配
- 线程 2 从 L2 释放互斥量
Singleton
创建了两个实例。每个线程 returns 都有自己的实例。
通过 L3 的检查,第 8 步不会发生,因为在第 7 步线程 2 的 _instance
视图与线程 1 的视图同步,因此只创建了一个 Singleton
的实例。
关于我提出的
public static Singleton getInstanceDC() {
if (_instance == null) { // Single Checked (1)
synchronized (Singleton.class) {
if (_instance == null) { // Double checked (2)
_instance = new Singleton();
}
}
}
return _instance;
}
为什么要使用第二个实例空检查条件。它可能有什么影响?
让我们对行进行编号,以便了解线程如何交错操作。
if (_instance == null) { // L1
synchronized (Singleton.class) { // L2
if (_instance == null) { // L3
_instance = new Singleton();// L4
}
}
}
让我们考虑一个不检查 L3 的交错。
- 线程 1 到达 L1 且
_instance
为null
- 线程 2 到达 L1 且
_instance
为null
- 线程 1 在 L2 获得互斥
- 线程 2 尝试在 L2 处获取互斥量但阻塞
- 线程 1 创建新实例并在 L4 分配
- 线程 1 从 L2 释放互斥量
- 线程 2 在 L2 获得互斥
- 线程 2 创建新实例并在 L4 分配
- 线程 2 从 L2 释放互斥量
Singleton
创建了两个实例。每个线程 returns 都有自己的实例。
通过 L3 的检查,第 8 步不会发生,因为在第 7 步线程 2 的 _instance
视图与线程 1 的视图同步,因此只创建了一个 Singleton
的实例。