Why is ConcurrentHashMap.putifAbsent safe?

I read for sympathy from yesterday, and I don’t know much of what ... However, some things begin to become clear ...
I understand why double locking check is unsafe (I wonder what the probability is that this is a rare condition), but volatilely fixes the problem in 1.5 + .... But I wonder if this happens with putifAbsent

as...

 myObj = new myObject("CodeMonkey"); cHashM.putIfAbsent("keyy",myObj); 

Then this ensures that myObj will be 100% intialiased when another thread executes cHashM.get() ??? Since this may be a link that is not fully initialized (problem with double locking check)

+6
source share
4 answers

If you call concurrentHashMap.get(key) and it returns an object, this object will be fully initialized. Each put (or putIfAbsent) will receive a specific lock in the form of a bucket and add an element to the bucket entries.

Now you can go through the code and notice that the get method does not receive the same lock. Therefore, you can argue that there may be an outdated reading, this is also not the case. The reason is that the value inside the record itself is volatile. Thus, you are sure to get the latest information.

+3
source

putIfAbsent ConcurrentHashMap method is the check-if-absent-then-set method. This is an atomic operation. But answer the following part: β€œThen it ensures that myObj will be 100% intialiased when another thread executes cHashM.get (),” it will depend on when the object is placed in the HashMap. Usually there is an incident before the priority, that is, if the caller becomes the first before the object is placed on the card, then null will be returned, otherwise the value will be returned.

+2
source

The relevant part of the documentation is as follows:

The effects of memory consistency: as with other parallel collections, actions in the thread before placing an object in ConcurrentMap as a key or value occur before accessing or deleting this object from ConcurrentMap to another thread before actions.

- java.util.ConcurrentMap

So yes, you have your own relationship before the relationship.

+2
source

I'm not an expert on this, but looking at the implementation of Segment in ConcurrentHashMap , I see that the volatile count field seems to be used to ensure proper visibility between threads. All read operations must read the count field, and all write operations must be written to it. From the comments in the class:

  Read operations can thus proceed without locking, but rely
 on selected uses of volatiles to ensure that completed
 write operations performed by other threads are
 noticed.  For most purposes, the "count" field, tracking the
 number of elements, serves as that volatile variable
 ensuring visibility.  This is convenient because this field
 needs to be read in many read operations anyway:

    - All (unsynchronized) read operations must first read the
      "count" field, and should not look at table entries if
      it is 0.

    - All (synchronized) write operations should write to
      the "count" field after structurally changing any bin.
      The operations must not take any action that could even
      momentarily cause a concurrent read operation to see
      inconsistent data.  This is made easier by the nature of
      the read operations in Map.  For example, no operation
      can reveal that the table has grown but the threshold
      has not yet been updated, so there are no atomicity
      requirements for this with respect to reads.
+1
source

Source: https://habr.com/ru/post/888069/


All Articles