英文:
Java double checked locking code explanation
问题
我有一个代码片段,我不理解,我会突出显示让我困惑的部分。
```java
private static final Object lock = new Object();
private static volatile YourObject instance;
public static YourObject getInstance() {
YourObject r = instance; // <---------- 这部分,为什么我们在这里赋值?
if (r == null) {
synchronized (lock) { // 在这里使用锁的好处是什么?
r = instance; // 假设instance为null,将通过第一个if (r == null),为什么要再次赋值?我完全不理解这一步的意义。
if (r == null) {
r = new YourObject();
instance = r;
}
}
}
return r;
}
我已经看过 https://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-examples,但它们的实现看起来是这样的,没有两次赋值。
public static ThreadSafeSingleton getInstanceUsingDoubleLocking(){
if(instance == null){
synchronized (ThreadSafeSingleton.class) {
if(instance == null){
instance = new ThreadSafeSingleton();
}
}
}
return instance;
}
<details>
<summary>英文:</summary>
I have a code snippet that I don't understand I will highlight the bit that confused me.
private static final Object lock = new Object();
private static volatile YourObject instance;
public static YourObject getInstance() {
YourObject r = instance; // <---------- This bit, why do we assign it here ?
if (r == null) {
synchronized (lock) { // What is the benefit of this lock in here
r = instance; // assuming instance is null which will pass the first if ( r == null, what do we assign it again ?? I don't get the idea of this step at all.
if (r == null) {
r = new YourObject();
instance = r;
}
}
}
return r;
}
I have seen https://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-examples but there implementation looks like this, which doesn't have two assignments.
public static ThreadSafeSingleton getInstanceUsingDoubleLocking(){
if(instance == null){
synchronized (ThreadSafeSingleton.class) {
if(instance == null){
instance = new ThreadSafeSingleton();
}
}
}
return instance;
}
</details>
# 答案1
**得分**: 2
YourObject r = instance; // <---------- This bit, why do we assign it here ?
在这里进行赋值是为了方便对局部变量进行推理。此处你确实需要局部变量。此外,读取 `volatile` 变量存在开销,可能不会被优化器合并。
synchronized (lock) { // What is the benefit of this lock in here
这个锁可以防止多个线程同时创建并分配不同的 `YourObject` 实例。
r = instance; // 假设 instance 为 null,会通过第一个 if 判断 (r == null),为什么要再次赋值?我完全不理解这一步的意义。
在第一次读取进行 `null` 检查和成功获取锁之间,`instance` 可能已经发生了变化。
无论如何,不要使用双重检查锁定 - 它会非常令人困惑,而且可能有更好的方法。
<details>
<summary>英文:</summary>
YourObject r = instance; // <---------- This bit, why do we assign it here ?
It is easier to reason about local variables, which you really want here. Also there is overhead in reading `volatile` variables that may not be merged by the optimiser.
synchronized (lock) { // What is the benefit of this lock in here
This is the lock that prevents multiple threads creating and assigning different instances of `YourObject` simultaneously.
r = instance; // assuming instance is null which will pass the first if ( r == null, what do we assign it again ?? I don't get the idea of this step at all.
`instance` may have changed between the first read for the `null` check and the lock being successfully acquired.
Anyway, don't use double-checked locking - it's very confusing and there's probably better ways.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论