8

来自文档:

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

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

4

2 回答 2

11

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

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

volatile int mCounter;

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

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

有关volatilevs.的更多信息synchronized,我推荐Brian Goetz的文章管理波动性

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

于 2012-11-28T05:31:35.517 回答
4

易失性执行以下操作:

-防止缓存线程中的值。

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

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

## 但是 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.第二个选项是使用AtomicInteger、AtomicLong、AtomicReference 等Atomic Classes

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

为什么 Volatile 行为怪异

于 2012-11-28T05:32:20.833 回答