使用volatile关键字时内存一致性错误的示例?
来自docs:
使用volatile变量可降低内存一致性错误的风险
但是这意味着有时候volatile变量不能正常工作? 奇怪的是如何使用它 – 我认为这是非常糟糕的代码,有时有时不工作。 我试过谷歌,但没有找到与volatile有关的示例内存一致性错误。 你能提出一个吗?
问题不在于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撰写的“ 管理易变性 ”一文
(*)我意识到使用AtomicInteger
可以更好地实现上述function; 这是一个人为的例子来说明一个观点。
易失性做到以下几点:
–它可以防止缓存线程中的值 。
–它确保具有对象字段值的副本的线程与存储器中存在的主副本协调。
–确保数据直接写入内存并从内存中读取。
##但是volatile失败的情况:
–使Non-Atomic statement Volatile
。
例如:
int count = 0; count++; // Increment operator is Not Atomic in java
##更好的选择:
遵循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等。
##看到这个链接,我问过类似你的问题:
为什么Volatile表现得很奇怪