我注意到ConcurrentHashMap
's compute
and computeIfAbsent
methods中有一个奇怪的结构:
Node<K,V> r = new ReservationNode<K,V>();
synchronized (r) {
//...
}
考虑到 JIT 很可能将本地对象视为无操作,同步本地对象有何意义?
最佳答案
在代码获取对象的监视器之后,对该对象的引用将存储到 tab
中,它是构成 ConcurrentHashMap
内容的全局可见的节点数组:
Node<K,V> r = new ReservationNode<K,V>();
synchronized (r) {
if (casTabAt(tab, i, null, r)) {
此时,在同一个 ConcurrentHashMap 上执行其他修改方法的其他线程在遍历全局数组时可能会遇到这个不完整的节点,换句话说,Node 引用已逃逸。
虽然在构造 ReservationNode
时,不可能对新创建的对象进行争用,但在与数组中找到的 Node
进行同步的其他方法中,可能会发生对该 Node
的争用。
这就像“优先级同步”。创建者在引用尚未转义的点进行同步,因此保证成功,而在引用转义的点,所有其他线程将不得不等待,以防万一它们恰好访问该 Node
。
关于java - 同步局部变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45977360/