来自docs:
使用volatile变量可降低内存一致性错误的风险
但这意味着有时候volatile变量不能正常工作? 奇怪的是如何使用 - 我认为这是非常糟糕的代码,有时有时不工作。我试过谷歌,但没有找到与volatile有关的示例内存一致性错误。你能提出一个吗?
答案 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
来确保数据完整性。
有关volatile
与synchronized
的详情,建议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等。
##看到这个链接,我问了一个类似你的问题: