让我们考虑以下 Java 代码
int x = 0;
int who = 1
Thread #1:
(1) x++;
(2) who = 2;
Thread #2
while(who == 1);
x++;
print x; ( the value should be equal to 2 but, perhaps, it is not* )
(我不知道 Java 内存模型——假设它是强内存模型——我的意思是:(1) 和 (2) 不会交换)
Java 内存模型保证对 32 位变量的访问/存储是原子的,因此我们的程序是安全的。但是,尽管如此,我们还是应该使用 volatile
属性,因为 *. x
的值可能等于1
,因为当Thread#2
读取时,x
可以保存在寄存器中.要解决这个问题,我们应该将 x
变量设为 volatile
。很清楚。
但是,那种情况呢:
int x = 0;
mutex m; ( just any mutex)
Thread #1:
mutex.lock()
x++;
mutex.unlock()
Thread #2
mutex.lock()
x++;
print x; // the value is always 2, why**?
mutex.unlock()
x
的值始终为 2
,但我们并未将其设为 volatile
。我是否正确理解锁定/解锁互斥量与插入内存屏障有关?
最佳答案
我会尽力解决这个问题。 Java 内存模型有点复杂,很难包含在单个 StackOverflow 帖子中。请参阅 Brian Goetz 的 Java Concurrency in Practice 了解完整故事。
The value of x is always 2 though we don't make it volatile. Do I correctly understand that locking/unlocking mutex is connected with inserting memory barriers?
首先如果要了解Java内存模型,总是Chapter 17 of the spec你想通读。
该规范说:
An unlock on a monitor happens-before every subsequent lock on that monitor.
是的,在您的显示器解锁时会发生内存可见性事件。 (我假设“互斥锁”是指监视器。java.utils.concurrent
包中的大多数锁和其他类也有happens-before 语义,请查看文档.)
Happens-before 是 Java 的意思,它不仅保证事件有序,而且保证内存可见性。
We say that a read r of a variable v is allowed to observe a write w
to v if, in the happens-before partial order of the execution trace:
r is not ordered before w (i.e., it is not the case that
hb(r, w)), and
there is no intervening write w' to v (i.e. no write w' to v such
that hb(w, w') and hb(w', r)).
Informally, a read r is allowed to see the result of a write w if there
is no happens-before ordering to prevent that read.
全部来自17.4.5 .通读起来有点困惑,但如果您通读它,信息就在那里。
关于java - volatile 与非 volatile ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43824389/