I noticed a weird construct in ConcurrentHashMap
's compute
and computeIfAbsent
methods:
Node<K,V> r = new ReservationNode<K,V>();
synchronized (r) {
//...
}
What is the point of synchronizing on a local object considering that the JIT will most likely treat it as a no-op?
Right after the code has acquired the object’s monitor, the reference to the object is stored into the
tab
which is the globally visible array of nodes which make up the contents of theConcurrentHashMap
:Right at this point, other threads executing other modification methods on the same
ConcurrentHashMap
might encounter this incomplete node while traversing the global array, in other words, theNode
reference has escaped.While at the point where the
ReservationNode
has been constructed, there is no possibility for contention on a newly created object, in the other methods, which are synchronizing onNode
s found in the array, there might be contention for exactly thatNode
.It’s like a “priority-synchronization”. The creator is synchronizing at a point where the reference has not been escaped yet therefore it is guaranteed to succeed while at the point where the reference escapes, all other threads will have to wait, in the unlikely (but still possible) event that they access exactly that
Node
.