在局部变量上同步

我注意到 ConcurrentHashMap 的 compute 和 computeIfAbsent 方法中有一个奇怪的构造:

Node<K,V> r = new ReservationNode<K,V>();
synchronized (r) {
  //...
}

考虑到 JIT 很可能会将其视为无操作,在本地对象上进行同步有什么意义?


答案 1

在代码获取对象的监视器之后,对对象的引用将存储在构成以下内容的全局可见节点数组中:tabConcurrentHashMap

Node<K,V> r = new ReservationNode<K,V>();
synchronized (r) {
    if (casTabAt(tab, i, null, r)) {

此时,在同一个上执行其他修改方法的其他线程在遍历全局数组时可能会遇到此不完整的节点,换句话说,引用已转义。ConcurrentHashMapNode

虽然在构造的位置,不可能对新创建的对象进行争用,但在数组中找到的s上同步的其他方法中,可能会争用该 。ReservationNodeNodeNode

这就像一个“优先级同步”。创建者在尚未转义引用的点上进行同步,因此可以保证成功,而在引用转义的点上,所有其他线程将不得不等待,在不太可能(但仍然可能)的事件中,它们恰好访问了该事件。Node


答案 2