gpt4 book ai didi

java - 非 volatile 双重检查锁定,这可能吗?

转载 作者:行者123 更新时间:2023-11-29 08:45:51 25 4
gpt4 key购买 nike

这是我的单例类。

静态 instance 字段不是 volatile 的,因此会出现重新排序/可见性问题。为了解决这个问题,实例 val 字段是最终的。由于实例是正确构造的,因此如果客户端看到实例,它们应该始终看到初始化的 val 字段。

    static class Singleton {
private static Singleton instance;
private final String val;
public Singleton() { this.val = "foo"; }

public static Singleton getInstance() {
if (instance == null)
synchronized (Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
return instance;
}
public String toString() { return "Singleton: " + val; }
}

但是还有另一个问题 - 我有两个不 protected “实例”字段读取,可以(?)重新排序,以便客户端可能得到 null 而不是实际值:

public static Singleton getInstance() {
Singleton temp = instance;
if (instance != null) return temp;
else { /* init singleton and return instance*/ }
}

为了解决这个问题,我觉得我可以引入局部变量:

public static Singleton getInstance() {
Singleton temp = instance;
if (temp == null)
synchronized (Singleton.class) {
if(instance == null) {
instance = new Singleton();
temp = instance;
}
}
return temp;
}

这似乎解决了问题,因为只有一个未 protected 值读取,因此不会发生任何真正邪恶的事情。但是......我刚刚修改了程序流程而没有(几乎?)改变它的单线程语义。这是否意味着编译器可以撤消我的解决方法,因为此转换是安全的,并且如果不与 volatile 建立适当的先行发生关系,就无法使此代码正常工作?

最佳答案

我不确定是否真的会发生对同一变量的读取重新排序,但可以保证局部变量不受其他线程 Activity 的影响。即使没有发生这样的读取重新排序,此保证也与您读取时可能同时更新的每个变量相关:如果您读取一个值并将其存储到局部变量中,您可以确保局部变量的值不会之后不会突然改变。当然,如果该值是引用,则该保证不适用于引用对象的字段。

相关句子可以在JLS §17.4.1中找到:

Local variables (§14.4), formal method parameters (§8.4.1), and exception handler parameters (§14.20) are never shared between threads and are unaffected by the memory model.

所以答案是否定的,不允许编译器撤销引入局部变量的解决方法。

关于java - 非 volatile 双重检查锁定,这可能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25443173/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com