gpt4 book ai didi

java - 对 volatile 关键字的一点说明

转载 作者:行者123 更新时间:2023-12-02 03:25:04 25 4
gpt4 key购买 nike

考虑 Java 并发实践中的片段 -

// Unsafe publication
public Holder holder;

public void initialize(){
holder = new holder(42);
}
<小时/>
public class Holder{
private int n;

public Holder(int n) {
this.n = n;
}

public void assertSanity(){
if (n != n)
throw new AssertionError("This statement is false.");
}
}

本书作者建议的解决方案之一是 -

public static Holder holder = new Holder(42);

如果唯一的要求是防止 AssertionError,那么这也可以正常工作 -

private final int n;

我的问题是此 stackoverflow thread 评论的后续问题作者:约翰·温特-

Actually, declaring the member field volatile still doesnt guarantee publication prior to holder being visible. You can look at ConcurrentHashMap's private method readUnderLock in which that takes this nuance into account. Though declaring holder as volatile does.

简单来说,他提出了两件事-

public volatile Holder holder;

public void initialize(){
holder = new holder(42);
}

上述解决方案能够完美运行吗?如果对对象的引用被声明为 volatile ,是否可以确保安全的对象发布?数组也是对象。声明数组引用并不使其元素成为线程安全的。

为什么这不能按照作者的建议工作-

public class Holder {
private volatile int n;

declaring the member field volatile still doesnt guarantee publication prior to holder being visible

即使成员字段已被声明为 volatile ,它也保证条件 n != n 将始终为 false,因此不会出现 AssertionError 。请提出建议。

最佳答案

虽然按照您的建议使用 volatile 会有所帮助,但在您可能碰巧尝试使用的许多其他情况下它不会有帮助。也就是说,很容易错误地使用 volatile,因此很难鼓励它,除非您可以确定您知道将使用哪些操作。

If a reference to an object is declared as volatile, does it ensures safe object publication?

这很大程度上取决于操作的顺序和类型。在这种情况下,写入

this.n = n;
// and then
holder = ...

holder的写入确保对this.n的写入必须可见(假设您也这样做)

Holder h = holder; // read barrier
// n must be set.
int n = this.n;

declaring the member field volatile still doesnt guarantee publication prior to holder being visible

我不同意这种情况。一旦您在另一个线程中获得了 holder,读取 n 时就不会像读取 volatile 变量一样看不到初始化的值。这是因为 holder 仅在 n 初始化后设置。

关于java - 对 volatile 关键字的一点说明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39053429/

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