Sure, here’s the translation: Java双重检查锁定代码解释

huangapple go评论153阅读模式
英文:

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&#39;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&#39;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;    // &lt;---------- 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;    // &lt;---------- 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&#39;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&#39;t use double-checked locking - it&#39;s very confusing and there&#39;s probably better ways.

</details>



huangapple
  • 本文由 发表于 2020年10月28日 05:14:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/64562998.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定