【发布时间】:2023-06-23 10:20:01
【问题描述】:
考虑以下 Java 程序:
static volatile int shared;
public static void main(final String[] args) {
final Runnable r = () -> {
shared = 1;
};
new Thread(r).start();
new Thread(r).start();
}
因为shared 被标记为volatile,我想说这个程序没有数据竞争。但是,如何基于 JLS(例如版本 11)来激发这一点?
第 17 章告诉我们:
当一个程序包含两个冲突的访问(第 17.4.1 节)时,这些访问没有按发生前的关系排序,则称为包含数据竞争。
我认为这是 JLS 提供的数据竞争的定义。然后我们有第 17.4.1 节告诉我们:
如果至少有一次访问是写入,则对同一变量的两次访问(读取或写入)称为冲突。
好的,因为我们有两次写入shared,所以我们在这里有冲突的访问。现在我们必须在两个写入之间建立起之前发生的关系,否则我们就会有比赛。然而,我没有设法找到为什么我们在这里有这种关系。第 17 章告诉我:
如果动作 x 与后续动作 y 同步,那么我们也有 hb(x, y)。
同一章告诉我:
对 volatile 变量 v(第 8.3.1.4 节)的写入与任何线程对 v 的所有后续读取同步(其中“后续”根据同步顺序定义)。
但在将写入关联到易失性变量之前,我还没有发现任何事情发生。这是为什么呢?
【问题讨论】:
-
对 volitile 变量的访问从不受到数据竞争的影响。这是根据“数据竞争”术语的定义。参见例如给定问题:*.com/questions/7805192/….
-
@Tsyvarev:当然,但我不明白它是如何“根据'数据竞争'的定义”——我们从哪里得到两个写入之间的发生前关系?还是有其他原因导致数据竞争定义不适用于我们的情况?
-
嗯,我的意思是在引用的短语“当一个程序包含两个冲突的访问......它被称为包含数据竞争”。他们的意思是访问“正常”变量。此短语不适用于 volatile 变量的访问。我现在没有这本书,但我很确定标准中明确说明了这种例外情况。
-
@Tsyvarev:我还没有看到任何这样的“明确说明”的例外。 “书”可在线获得,您能否提供一个链接到说明此例外的相关部分?
标签: language-lawyer volatile java-memory-model happens-before data-race