Java 在同步块中发生之前
我需要一些帮助来理解 Java 内存模型。以下是一个掌握基本概念的通用示例:
Image 我有一个名为 Shared
的对象实例和两个线程 A
和 <代码>B。此外,还有某种带有同步 put
和 take
的 Queue
。
线程A
在put
方法之前和之中修改Shared
实例。
问题 1:当 B
通过同步 获取
-方法?Shared
对象实例时,A
的所有更改都可见>采用
问题 2:一旦 A
离开同步的 put
方法,内存缓存就会被刷新(Shared
上的所有更改都可见)。如果 A
在 put
方法中调用 wait()
会发生什么情况?即使 A
尚未退出 synchronized
方法,B
也会看到对 Shared
所做的更改吗?调用 wait() 时缓存是否也会被刷新?
I need some help understanding the Java memory model.The following is a gerneric example to grasp the basic concept:
Image I have an object instance called Shared
and two threads A
and B
. Furthermore there is some kind of Queue
with a synchronized put
and take
.
Thread A
modifies the Shared
-instance before and in the put
method.
Question 1: All changes from A
are visible when B
gets the Shared
-object instance through the synchronized take
-method?
Question 2: The memory cache is flushed (all changes on Shared
are visible) as soon as A
leaves the synchronized put
-method. What exaclty happens if wait()
is called in the put
-method by A
? Will B
also see the changes done to Shared
even though A
hasn't yet exited the synchronized
-method? Is the cache also flushed when calling wait()
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
答案1:是的。因为 take() 和 put() 都是同步的。因此,在 B 执行 take() 之前,A 应该已经离开同步块,而离开同步块意味着刷新内存缓存(内存栅栏/屏障)。
答案2:是的。因为当调用wait()时,线程必须交出锁,这将再次导致内存刷新。
编辑:我认为您所追求的是缓存写入内存是否发生在同步块退出或释放锁时。答案是缓存写入内存发生在释放锁时。
Answer 1: Yes. Because both take() and put() are synchronized. So before B could execute take(), A should have left the synchronized block and leaving the synchronized block means flushing memory cache(memory fence/barrier).
Answer 2: Yes. Because when wait() is called, the thread has to surrender the lock, which will again cause memory flushing.
EDIT: I think what you are after is that whether cache-write-to-memory happens on exit of synchronized block or release of lock. The answer is cache-write-to-memory happens on release of lock.
第一个问题的答案是肯定的,因为同步点(存在于 put 和 take 中)引入了隐式内存栅栏。
对于第二个问题,取决于 A 在将对象添加到 Shared 之前还是之后调用 wait。如果是之前,那么显然共享没有变化,因此 B 没有什么新的可看。
编辑:如果 A 在之后调用 wait,则更改是可见的,因为您必须在添加之前获取锁,然后在等待时释放它,这也会引入栅栏。
所以这两种情况的答案都是肯定的。
The answer to your first questions is Yes, because synchronization points (present in put and take) introduce implicit memory fences.
For the second question, it depends if A calls wait before or after the object is added to
Shared
. If it is before, then obviously there is no change to shared and so B has nothing new to see.Edit: If A calls wait after, then the change is visible because you had to acquire a lock before adding and then release it when waiting which also introduces a fence.
So the answer is Yes in both cases.
引用自 JSR 133(Java 内存模型)常见问题解答 - 什么意思同步做什么?:
它说当监视器被释放时,会将缓存刷新到内存中。请注意,虽然监视器在退出同步块时被释放,但它也在调用 wait 方法时被释放。因此,我希望更改会在 #wait() 调用上刷新,并由另一个线程拾取,前提是它之前在同一监视器上等待。
Quoting from JSR 133 (Java Memory Model) FAQ - What does synchronization do? :
It says that flushing the cache to memory happens when a monitor is released. Note that while the monitor is released while exiting a synchronized block, it is also released while calling the wait method. So I'd expect the changes to be flushed on the #wait() call and to be picked up by the other thread provided it was waiting earlier on the same monitor.