gpt4 book ai didi

java - 对数组和数组元素的 AtomicReference 更改可见性

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:08:56 26 4
gpt4 key购买 nike

Java 是否保证 线程 A 在将数组引用存储在 AtomicReference 之前对数组元素所做的更新将始终对 线程 B 获取此引用?

换句话说,执行此操作的可能输出是什么:

class References {
AtomicReference<String[]> refs = new AtomicReference<>(new String[]{"first"});

public void add(String s) {
refs.updateAndGet(oldRefs -> {
String[] newRefs = new String[oldRefs.length + 1];
System.arraycopy(oldRefs, 0, newRefs, 0, oldRefs.length);
newRefs[oldRefs.length] = s;
return newRefs;
});
}

public static void main(String[] args) {
References r = new References();
new Thread(() -> r.add("second")).start();
System.out.println(Arrays.toString(r.refs.get()));
}
}

上面的代码是否只能打印[first][first, second],或者是否也可以得到类似[first, null]的结果 还是 [null, null]

java.util.concurrent.atomic 的 javadoc 指出:

compareAndSet and all other read-and-update operations such as getAndIncrement have the memory effects of both reading and writing volatile variables.

这似乎没有对数组的非 volatile 元素做出任何保证,只有数组引用本身。

最佳答案

对变量的 volatile 写入将保证在它之前发生的所有事情都将在随后对同一变量的 volatile 读取之前发生。

相关规则来自JLS是:

17.4.4. Synchronization Order

  • A write to a volatile variable v (§8.3.1.4) synchronizes-with all subsequent reads of v by any thread (where "subsequent" is defined according to the synchronization order).

17.4.5. Happens-before Order

Two actions can be ordered by a happens-before relationship. If one action happens-before another, then the first is visible to and ordered before the second.

If we have two actions x and y, we write hb(x, y) to indicate that x happens-before y.

  • If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).
  • If an action x synchronizes-with a following action y, then we also have hb(x, y).

  • If hb(x, y) and hb(y, z), then hb(x, z).

由于 AtomicReference 保证您的数组引用仅以易变的方式存储/加载(并且一旦写入,您就不会修改现有数组),这足以保证结果的可见性任何调用 refs.get()System.arrayCopy()(及其后面的行)。

但是该构造仍然不是完全无懈可击,因为任何通过 refs.get() 获取数组引用的人都可以继续对元素进行更改,而无需AtomicReference 的保护。

CopyOnWriteArrayList 的工作方式与此非常相似(它使用 ReentrantLockvolatile 数组字段的组合,而不是 AtomicReference ),除了它还保证没有人可以获取底层数组并以不安全的方式使用它。

关于java - 对数组和数组元素的 AtomicReference 更改可见性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31202613/

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