Reputation: 3641
I have been reading for concurency since yesterday and i dont know much things... However some things are starting to getting clear...
I understand why double check locking isnt safe (i wonder what is the propability the rare condition to occur) but volatile fixes the issue in 1.5 +....
But i wonder if this occurs with putifAbsent
like...
myObj = new myObject("CodeMonkey");
cHashM.putIfAbsent("keyy",myObj);
Then does this ensures that myObj
would be 100% intialiased when another thread does a cHashM.get()
??? Because it could have a reference isnt completely initialised (the double check lock problem)
Upvotes: 11
Views: 10883
Reputation: 40256
If you invoke concurrentHashMap.get(key)
and it returns an object, that object is guaranteed to be fully initialized. Each put (or putIfAbsent) will obtain a bucket specific lock and will append the element to the bucket's entries.
Now you may go through the code and notice that the get method doesnt obtain this same lock. So you can argue that there can be an out of date read, that isn't true either. The reason here is that value within the entry itself is volatile. So you will be sure to get the most up to date read.
Upvotes: 5
Reputation: 147164
The relevant part of the documentation is this:
Memory consistency effects: As with other concurrent collections, actions in a thread prior to placing an object into a ConcurrentMap as a key or value happen-before actions subsequent to the access or removal of that object from the ConcurrentMap in another thread.
So, yes you have your happens-before relationship.
Upvotes: 3
Reputation: 5582
putIfAbsent
method in ConcurrentHashMap
is check-if-absent-then-set method. It's an atomic operation. But to answer the following part: "Then does this ensures that myObj would be 100% intialiased when another thread does a cHashM.get() ", it would depend on when the object is put into the HashMap. Usually there is a happens-before precedence, i.e., if the caller gets first before the object is placed in the map, then null
would be returned, else the value would be returned.
Upvotes: 5
Reputation: 110054
I'm not an expert on this, but looking at the implementation of Segment
in ConcurrentHashMap
I see that the volatile
field count
appears to be used to ensure proper visibility between threads. All read operations have to read the count
field and all write operations have to write to it. From 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.
Upvotes: 1