gpt4 book ai didi

共享字符数组上的 Java 多线程竞争条件

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:47:21 25 4
gpt4 key购买 nike

假设我有以下内容:

char[] shared = new char[]{'a', 'b'};
ExecutorService exec = Executors.newCachedThreadPool();
Future<?> f1 = exec.submit(() -> shared[0] = 'A');
Future<?> f2 = exec.submit(() -> shared[1] = 'B');
f1.get(); f2.get();
System.out.println(shared);

我希望这通常会打印:

'AB'

但是这是否也可以打印:

'aB'

'bA'

我想知道是否由于 shared 不是 volatile 的,一个线程可能会在将其更改保存到其对应的 char 元素时保存其相邻字节,这在其本地处理器中是陈旧的缓存,并踩踏另一个线程所做的更改。我觉得这个问题的答案是“否”,因为我认为这会违反 Java 的内存模型,该模型表示无论何时加入线程,它完成的所有操作都发生在加入之前。但如果是这样的话,那么我很好奇这是如何防止的?我的理解是,当字节被刷新时,整个缓存行都会被刷新,我想一个 char[] 数组会有多个元素位于同一个缓存行中。

最佳答案

这已在 Java Language Specification 中指定正是:

17.6. Word Tearing

One consideration for implementations of the Java Virtual Machine is that every field and array element is considered distinct; updates to one field or element must not interact with reads or updates of any other field or element. In particular, two threads that update adjacent elements of a byte array separately must not interfere or interact and do not need synchronization to ensure sequential consistency.

Some processors do not provide the ability to write to a single byte. It would be illegal to implement byte array updates on such a processor by simply reading an entire word, updating the appropriate byte, and then writing the entire word back to memory. This problem is sometimes known as word tearing, and on processors that cannot easily update a single byte in isolation some other approach will be required.

在最坏的情况下,这意味着使用 CAS 指令或类似指令执行此类数组更新,以确保不会发生中间更新。但据我所知,x86/x64 架构不受此影响,因为它有修改较小尺寸项目的指令,并且它将处理使其他 CPU 核心的缓存行无效以确保其他 CPU 核心将获取更改的内容执行自己的更新之前的数据。当然,这仍然比两个 CPU 内核在不同的缓存行上执行更新要慢。

关于共享字符数组上的 Java 多线程竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50596641/

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