Is Concurrenthashmap Totally Safe

ConcurrentHashMap operations are thread safe

From Wikipedia:

A piece of code is thread-safe if it only manipulates shared data structures in a manner that guarantees safe execution by multiple threads at the same time.

To answer your expanded question, if multiple threads were to execute put() the effect would be that the last one to run would set the value for that key in the map. All of the puts would happen in some sequence, but they would not interfere with each other. How might they interfere without a concurrency guarantee? Well, put() returns null if no value had previously been associated with the mapping or the previous value. If two puts happened on a non-concurrent map they can both get the same return value from the put.

This sequence is possible without concurrency:

Thread1: map.put("key1", "value1") => null

then

Thread2: map.put("key2", "value2") => "value1"
Thread3: map.put("key3", "value3") => "value1"

If Thread3 got in just after Thread2, it might see "value1" rather than "value2", even though that's not what it replaces. This won't happen in a concurrent map.

Is values() of ConcurrentHashMap thread safe?

Is iterating over result of values() method the recommended way of fetching results without getting a ConcurrentModificationException?

Yes. It is the recommended way, and you won't get a ConcurrentModificationException.

As the package level javadoc states:

Most concurrent Collection implementations (including most Queues) also differ from the usual java.util conventions in that their Iterators and Spliterators provide weakly consistent rather than fast-fail traversal:

  • they may proceed concurrently with other operations
  • they will never throw ConcurrentModificationException
  • they are guaranteed to traverse elements as they existed upon construction exactly once, and may (but are not guaranteed to) reflect any modifications subsequent to construction.


Is the below code thread safe?

  for (String name: myMap.values()) {
System.out.println("name": + name);
}

Yes ... with some qualifications.

Thread safety really means that the code works according to its specified behavior in a multi-threaded application. The problem is that you haven't said clearly what you expect the code to actually do.

What we can say is the following:

  1. The iteration will see values as per the previously stated guarantees.
  2. The memory model guarantees mean that there shouldn't be any nasty behavior with stale values ... unless you mutate value objects after putting them into the map. (If you do that, then the object's methods need to be implemented to cope with that; e.g. they may need to be synchronized. This is moot for String values, since they are immutable.)

Can ConcurrentHashMap put() method be not thread-safe?

All methods within ConcurrentHashMap might be thread-safe, but this does not mean that it synchronizes on the ConcurrentHashMap object itself. What you can do is synchronize put and the map access code on the same reference. Your put code would have to be changed to this:

synchronized (map) {
map.put("One", 2);
}

And your access code can remain like:

synchronized (map) {
Integer number = map.get("One");
System.out.println(number == map.get("One"));
}

This will never be able to print false.

Is iterating ConcurrentHashMap values thread safe?

What does it mean?

That means that each iterator you obtain from a ConcurrentHashMap is designed to be used by a single thread and should not be passed around. This includes the syntactic sugar that the for-each loop provides.

What happens if I try to iterate the map with two threads at the same time?

It will work as expected if each of the threads uses it's own iterator.

What happens if I put or remove a value from the map while iterating it?

It is guaranteed that things will not break if you do this (that's part of what the "concurrent" in ConcurrentHashMap means). However, there is no guarantee that one thread will see the changes to the map that the other thread performs (without obtaining a new iterator from the map). The iterator is guaranteed to reflect the state of the map at the time of it's creation. Futher changes may be reflected in the iterator, but they do not have to be.

In conclusion, a statement like

for (Object o : someConcurrentHashMap.entrySet()) {
// ...
}

will be fine (or at least safe) almost every time you see it.

Concurrent HashMap thread safety and happens-before relationship

Does this mean aggregate operations like putAll and clear are still a risky bet ?

Their promise that "retrieval operations...do not block" puts some major restrictions on what else they can promise. For example, a map.get(k) call must immediately return either null or some v that was earlier put(k,v) with the same k. The get(k) call can't wait for some other thread to complete a map.putAll(someEnormousOtherMap) call. They promised that it would not block!

Basically they can't keep that promise, unless the only operations that appear to be atomic are the insertions/removals/replacements of individual key/value pairs. The only way that aggragate operations can be implemented without breaking the non-blocking-get() promise is to implement them as non-atomic sequences of calls to the atomic primitives that operate on one key/value pair at a time.

ConcurrentHashMap vs ConcurrentSkipListMap clarification

ConcurrentHashMap

Retrievals reflect the results of the most recently completed update
operations holding upon their onset. For aggregate operations such as
putAll and clear, concurrent retrievals may reflect insertion or
removal of only some entries.

it uses volatile semantics for get(key). In case when Thread1 calls put(key1, value1) and right after that Thread2 calls get(key1), Thread2 wouldn't wait Thread1 to finish its put, they are not synchronized with each other and Thread2 can get old associated value. But if put(key1, value1) was finished in Thread1 before Thread2 tries to get(key1) then Thread2 is guaranteed to get this update (value1).

ConcurrentSkipListMap is sorted and provides

expected average log(n) time cost for the containsKey, get,
put and remove operations and their variants

ConcurrentSkipListMap isn't so fast, but is useful when you need sorted thread-safe map.



Related Topics



Leave a reply



Submit