使用volatile关键字时内存一致性错误的示例?

时间:2012-11-28 05:22:22

标签: java multithreading memory volatile consistency

来自docs:

  

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

但这意味着有时候volatile变量不能正常工作? 奇怪的是如何使用 - 我认为这是非常糟糕的代码,有时有时不工作。我试过谷歌,但没有找到与volatile有关的示例内存一致性错误。你能提出一个吗?

2 个答案:

答案 0 :(得分:10)

问题不在于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可以更好地实现上述功能。这是一个人为的例子来说明这一点。

答案 1 :(得分:4)

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