0

You can ensure that changes one thread makes to a variable can be seen on other threads by making the variable volatile, or by having both threads synchronize on something. If the thing being changed is a java.util.ConcurrentHashMap, does it make sense to create a memory barrier by declaring the type of the variable holding this map as volatile, or are readers accessing the map (say via myMap.values()) going to get the latest possible view anyway? For context I have a heavy reading, light writing scenario where I am switching my lock free read solution to a ConcurrentHashMap.

Community
  • 1
  • 1
MilesHampson
  • 2,069
  • 24
  • 43
  • Declaring the field `volatile` is not what you want since you are not modifying the field value itself. Querying the map will give the latest results. – obataku Aug 17 '12 at 07:26
  • Right, and I assume that applies to AtomicReference as well. The reference being not thread local has no effect on the thing being referenced, in this case the map. – MilesHampson Aug 17 '12 at 09:40
  • correct, since the value of the field is never changed and all of the memory consistency work for the collection is done internally by `ConcurrentHashMap`. – obataku Aug 17 '12 at 18:39

4 Answers4

3

ConcurrentHashMap guarantees that there is a happens-before relationship between writes and subsequent reads. So yes, when you read (get), you will see the most recent changes that have been "committed" (put has returned).

Note: this does not apply to iterators as explained in the javadoc.

assylias
  • 321,522
  • 82
  • 660
  • 783
2

The variable "holding" the map is a reference or pointer to the map object (respectively (simplified) to the memory address where the map is stored). Making it volatile would only affect the pointer, not the map object itself. As long as you always use the same Map-Object and ensure that the map is fully initialized before the threads use it, you don't have to use "volatile references" to it. The concurrency is handled transparently inside the concurrent hash map.

Pyranja
  • 3,529
  • 22
  • 24
2

Yes, ConcurrentHashMap gives the latest views. If you refer the javadocs at http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ConcurrentHashMap.html#get(java.lang.Object) it is clearly written that

Retrievals reflect the results of the most recently completed update operations holding upon their onset

It has some more details and I would suggest you go and read it.

Besides, as already noted using volatile is not what you want as it will only affect the pointer and not the actual contents of the map.

Neal
  • 3,119
  • 4
  • 27
  • 32
1

All you need to do is make sure that the reference holding the map is final, so you get a final field fence that guarantees you see a properly initialised map and that the reference itself is not changed.

As others point out, ConcurrentHashMap will guarantee visibility/happens-before of writes internally, as all of the java.util.concurrent.* collections do. You should however use the conditional writes exposed on the ConcurrentMap interface to avoid data-races in your writes.

Jed Wesley-Smith
  • 4,686
  • 18
  • 20
  • *"All you need to do is make sure that the reference holding the map is final"* I don't think that's necessary. – assylias Aug 17 '12 at 09:34
  • Making the reference final does have the effect under the JMM of guaranteeing that a non-null reference will be in a post construction state. ConcurrentHashMap already does the right thing internally so you'll never have a visibility issue, but someone may still change the reference itself so it is still useful to make it final to ensure correctness. – Jed Wesley-Smith Aug 20 '12 at 01:03