29

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?

assylias
  • 321,522
  • 82
  • 660
  • 783

1 Answers1

26

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 the ConcurrentHashMap:

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

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, the Node 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 on Nodes found in the array, there might be contention for exactly that Node.

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.

TheLostMind
  • 35,966
  • 12
  • 68
  • 104
Holger
  • 285,553
  • 42
  • 434
  • 765
  • it's possible that the node needs to do some race sensitive housekeeping about being in the wild rather than just constructed. – ratchet freak Oct 21 '14 at 14:55
  • 1
    @ratchet freak: as the type name `ReservationNode` suggests, that node primarily exists for mutual exclusion of updates to the same hash bucket. That’s required for the atomicity guaranty of `computeIfAbsent`: once the computation has been started, no other updates for the same key are allowed. – Holger Oct 21 '14 at 17:58
  • @Holger I also have similar question related to synchronization [here](https://stackoverflow.com/questions/47783712/do-not-share-same-socket-between-two-threads-at-the-same-time/) where I am using synchronization on socket object and I am trying to see whether I can get rid of synchronization altogether or not through some other efficient way? Wanted to see if you can help out. – john Dec 16 '17 at 05:56