【发布时间】:2017-12-31 10:58:39
【问题描述】:
看了一点java的内存模型和同步之后,提出了几个问题:
即使线程 1 同步写入,虽然写入的效果会被刷新到主内存,但线程 2 仍然看不到它们,因为读取来自 1 级缓存。所以同步写入只能防止写入冲突。 (Java thread-safe write-only hashmap)
其次,当一个同步方法退出时,它会自动与任何后续对同一对象的同步方法调用建立起之前的关系。这保证了对象状态的更改对所有线程都是可见的。 (https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html)
第三个网站(我再也找不到它了,抱歉)说,对任何对象的每次更改——它不关心引用来自哪里——都会在方法离开同步块并建立时刷新到内存中发生在的情况。
我的问题是:
退出同步块后真正刷新回内存的是什么? (正如一些网站也说过,只有获得锁的对象才会被刷新。)
在这种情况下,happens-before-relaitonship 是什么意思?进入区块时会从内存中重新读取什么,什么不是?
-
锁是如何实现这个功能的(来自https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Lock.html):
所有 Lock 实现必须强制执行与内置监视器锁提供的相同内存同步语义,如 Java™ 语言规范第 17.4 节所述:
成功的锁定操作与成功的锁定操作具有相同的内存同步效果。 成功的解锁操作与成功的解锁操作具有相同的内存同步效果。 不成功的锁定和解锁操作,以及重入锁定/解锁操作,不需要任何内存同步效果。
如果我认为所有内容都将被重新读取和刷新的假设是正确的,那么这可以通过在锁定和解锁功能中使用同步块来实现(这通常也是必需的),对吧?如果错了,这个功能怎么实现?
提前谢谢你!
【问题讨论】:
-
如果你想知道 Java 内存模型是如何工作的,你应该强烈考虑阅读Java memory model。
-
同步块在块末尾添加一个full membar,并强制在处理进一步指令之前完全刷新 CPU 写入缓存。
-
"这是通过在锁定和解锁功能中使用同步块来实现的(大多数情况下也是必需的)" - 你弄错了。 A
synchronized-block uses the intrinsic object-lock. -
等等,什么?你的意思是每个对象持有的锁,对吧?我说的是 java.util.concurrent.locks.Lock 的自定义实现,而不是监视器监督的对象锁。 (或者我是不是理解错了什么?)或者更具体地说:java.util.concurrent.locks.Lock 的实现如何确保与 synchronize-blocks 保证的内存功能相同?
-
看看source code@Quaffel ...
标签: java concurrency synchronized memory-model