【问题标题】:Volatile Variables and Happens before ordering [duplicate]易变变量并在订购前发生[重复]
【发布时间】:2010-10-19 17:39:51
【问题描述】:

我有两个线程:

线程:1

a = 1;
x = b;

线程:2

b = 1
y = a

这里 a 和 b 被声明为 volatile。我不明白如何在 a = 1; 之间创建“之前发生”的边缘;和 y = a;在 x = b 之间;和 b = 1;

我知道通过使用 volatile 变量可以防止从线程缓存中读取过时的值。但是 volatile 变量如何确保在排序之前发生。

具体来说,我没看懂:

发生对 volatile 字段的写入 在每次后续阅读之前 相同的字段。

锄头有用吗?

【问题讨论】:

标签: java volatile


【解决方案1】:

对 volatile 字段的写入发生在对同一字段的每次后续读取之前。

这里重要的词是“后续”。

这里是 Java 语言规范 17.4.4 Synchronization Order 的相关部分:

每次执行都有一个同步顺序。同步顺序是执行的所有同步操作的总顺序。对于每个线程 t,t 中的同步动作(第 17.4.2 节)的同步顺序与 t 的程序顺序(第 17.4.3 节)一致。 同步动作导致动作上的同步关系,定义如下:

  • [...]
  • 对 volatile 变量(第 8.3.1.4 节)v 的写入与任何线程对 v 的所有后续读取同步(其中后续根据同步顺序定义)。

注意最后一部分。所以它的意思是,如果你考虑程序动作的任何总排序,任何在总排序中比写入更晚的 volatile 变量的读取都不能“错过”写入。

【讨论】:

  • "对于每个线程 t,同步动作的同步顺序..." volatile 本身并不能确定线程之间的同步顺序吗?
  • 我也有同样的问题。发现 java 规范有点神秘。
  • @pst:Volatile 按total 顺序运行,而不是特定线程的顺序。这实际上意味着一个线程不能在不检查是否有其他线程执行写入的情况下读取 volatile 变量。
  • @JonSkeet 我阅读了 JLS,但我不知道 Synchronization OrderHappends-before Order 相同,Happens-before Order 适用于发生两个冲突访问时。
  • @JonSkeet 正如你所说:“如果不检查是否有任何其他线程执行了写入,线程就无法读取 volatile 变量。”但是如果一个线程介于写入操作和第二个线程读取它之间会发生什么!我错了吗 ??这不是原子操作的竞争条件吗?请回复。
【解决方案2】:

要进行分析,首先列出所有可能的同步顺序。它们必须与编程顺序一致。在您的示例中,有 6 个可能的订单。

 1       2       3       4       5       6
w(a)    w(a)    w(b)    w(a)    w(b)    w(b) 
r(b)    w(b)    w(a)    w(b)    w(a)    r(a)
w(b)    r(b)    r(b)    r(a)    r(a)    w(a)
r(a)    r(a)    r(a)    r(b)    r(b)    r(b)

每个顺序都建立了一些先发生的关系。在 (1) 中,我们有 w(a) 发生在 r(a) 之前。在 (6) 中,我们有 w(b) 发生在 r(b) 之前。在 (2)-(5) 中,我们都有。

对于每一个可能的顺序,给定它所建立的happens-before关系,您需要分析执行以确保它按照您的意愿行事。

如果这听起来太难,那就是。在现实生活中,我们通常将自己限制在更简单的情况下,即只有一个对象被锁定/释放,或者只有一个 volatile 变量被读写。那就不太复杂了。

【讨论】:

    【解决方案3】:

    在每次后续读取同一字段之前,都会对 volatile 字段进行写入。

    这段文字令人困惑。它将发生之前的关系限制为发生在读取之前的写入!它只是说读取发生在之后,实际上发生在之后。

    换句话说,它试图说的是读取不会发生在写入期间,并且如果有其他发生之前的关系导致读取发生在写入,读取将具有该写入的值。

    请参阅 JLS 部分 17.4.4 Synchronization Order,它在此上下文中定义了“后续”一词。

    【讨论】:

      猜你喜欢
      • 2015-07-26
      • 2018-08-09
      • 2020-06-20
      • 2020-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-16
      相关资源
      最近更新 更多