【问题标题】:Example of a memory consistency error when using volatile keyword?使用 volatile 关键字时出现内存一致性错误的示例?
【发布时间】:2012-11-28 05:22:22
【问题描述】:

来自文档:

使用 volatile 变量可降低内存一致性错误的风险

但这意味着有时 volatile 变量不能正常工作? 奇怪的是如何使用它——在我看来,这是非常糟糕的代码,有时工作有时不工作。我尝试谷歌,但没有找到易失性的示例内存一致性错误。你能推荐一个吗?

【问题讨论】:

标签: java multithreading memory volatile consistency


【解决方案1】:

问题不在于volatile 工作不可靠。它总是按应有的方式工作。问题是它应该工作的方式有时不足以进行并发控制。如果在错误的情况下使用volatile,仍然会出现内存一致性错误。

volatile 变量将始终将任何写入传播到所有线程。但是,假设您需要在各个线程之间增加变量。这样做(*)

volatile int mCounter;

// later, in some code that might be executed simultaneously on multiple threads:
mCounter++;

有可能会错过计数器增量。这是因为mCounter 的值需要先被每个线程读取,然后才能写入新值。在这两个步骤之间,另一个线程可能更改了mCounter 的值。在这种情况下,您需要依靠 synchronized 块而不是 volatile 来确保数据完整性。

有关volatilesynchronized 的更多信息,我推荐Brian Goetz 的文章Managing volatility

(*) 我意识到使用AtomicInteger 会更好地实现上述内容;这是一个人为的例子来说明一个观点。

【讨论】:

    【解决方案2】:

    Volatile 执行以下操作:

    -防止在线程中缓存值

    - 它确保拥有对象字段值副本的线程与内存中存在的主副本相一致。

    -确保数据直接写入内存并从内存本身读取。

    ##但是volatile失败的条件:

    - 制作Non-Atomic statement Volatile

    例如:

    int count = 0;
    
    count++;  // Increment operator is Not Atomic in java
    

    ## 更好的选择:

    1.最好关注Brian's Rule

    When ever we write a variable which is next to be read by another thread, or when we are reading a variable which is written just by another thread, it needs to be synchronized. The shared fields must be made private, making the read and write methods/atomic statements synchronized.

    2.第二种选择是使用Atomic Classes,例如AtomicInteger、AtomicLong、AtomicReference等

    ## 看到这个链接,我也问过和你类似的问题:

    Why Volatile is behaving weirdly

    【讨论】:

      猜你喜欢
      • 2014-08-20
      • 2020-12-18
      • 1970-01-01
      • 2012-06-01
      • 1970-01-01
      • 2019-12-16
      • 2011-02-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多