0

考虑以下 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 的所有后续读取同步(其中“后续”根据同步顺序定义)。

但是在将写入关联到 volatile 变量之前,我还没有发现任何事情发生。这是为什么?

4

1 回答 1

2

对volatile变量的访问永远不会受到数据竞争的影响。

从 JLS 中不是很明显,但在短语中

(第 17.4.1 节)如果至少有一个访问是写入,则对同一变量的两次访问(读取或写入)称为冲突。

术语“读”和“写”不是通用的,但在下一节“17.4.2 操作”中描述为对非易失性变量的访问:

读取(正常或非易失性)。读取变量。

写入(正常或非易失性)。写一个变量。

在该部分中,对volatile变量的访问被归类为Synchronization actions的一部分,具有不同的术语“Volatile read”和“Volatile write”:

易失性阅读。变量的易失性读取。

易失性写入。变量的易失性写入。

因为只有(非易失性)读取和写入可能会发生冲突,所以只有那些访问可能包含数据竞争易失性读取和写入永远不会发生冲突,也永远不会包含数据竞争

于 2019-03-20T11:02:17.120 回答