我注意到 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
上同步的其他方法中不可能争用新创建的对象在数组中找到 s,则可能恰好争用该 Node
。
这就像“优先同步”。创建者在引用尚未转义的点进行同步,因此保证成功,而在引用转义的点,所有其他线程将不得不等待,在他们访问的不太可能(但仍然可能)的事件中正是那个Node
。
关于java - 在局部变量上同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26482149/