gpt4 book ai didi

Java:保证非最终引用字段永远不会被读取为空的正确方法是什么?

转载 作者:搜寻专家 更新时间:2023-10-30 21:26:28 26 4
gpt4 key购买 nike

我正在尝试解决一个简单的问题,但我掉进了 Java 内存模型的兔子洞。

编写包含 non-final 引用字段的 Java 类的最简单和/或最有效(此处为判断调用)但无竞争(根据 JMM 精确定义)的方法是什么它在构造函数中被初始化为非空值并且随后从未更改,这样任何其他线程对该字段的后续访问都不会看到非空值?

破损的开始示例:

public class Holder {

private Object value;

public Holder(Object value) {
if (value == null)
throw NullPointerException();
this.value = value;
}

public Object getValue() { // this could return null!
return this.value;
}
}

并根据this post ,标记字段 volatile 甚至不起作用!

public class Holder {

private volatile Object value;

public Holder(Object value) {
if (value == null)
throw NullPointerException();
this.value = value;
}

public Object getValue() { // this STILL could return null!!
return this.value;
}
}

这是我们能做的最好的了吗??

public class Holder {

private Object value;

public Holder(Object value) {
if (value == null)
throw NullPointerException();
synchronized (this) {
this.value = value;
}
}

public synchronized Object getValue() {
return this.value;
}
}

好的,那这个呢?

public class Holder {

private Object value;

public Holder(Object value) {
if (value == null)
throw NullPointerException();
this.value = value;
synchronized (this) { }
}

public synchronized Object getValue() {
return this.value;
}
}

旁注:related question询问如何在不使用任何 volatile 或同步的情况下执行此操作,这当然是不可能的。

最佳答案

要在 Java 中安全地发布一个非不可变对象(immutable对象),您需要同步对象的构造和对该对象的共享引用的写入。不仅仅是该对象的内部结构这个问题很重要。

如果您在没有适当同步的情况下发布一个对象,通过重新排序,如果在构造函数完成之前发布了对对象的引用,则 Holder 对象的使用者仍然可以看到部分构造的对象。例如Double-checked locking没有 volatile

有几种安全发布对象的方法:

  • 从静态初始化程序初始化引用;
  • 将对它的引用存储到 volatile 字段或 AtomicReference
  • 将对它的引用存储到正确构造的对象的最终字段中;或者
  • 将对它的引用存储到一个由锁适当保护的字段中。

请注意,这些要点是在讨论对 Holder 对象的引用,而不是类的字段。

所以最简单的方法是第一个选项:

public static Holder holder = new Holder("Some value");

任何访问静态字段的线程都将看到一个正确构造的 Holder 对象。

参见 Java Concurrency in Practice 的第 3.5.3 节“安全发布习语” .有关不安全发布的更多信息,请参阅第 16.2.1 节 Java Concurrency in Practice .

关于Java:保证非最终引用字段永远不会被读取为空的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38839456/

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