Is Iterating Concurrenthashmap Values Thread Safe

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.

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.)

Is ConcurrentHashMap's forEach method thread-safe?

It depends what you mean by thread-safe.

  • If you're okay with other threads being able to modify the map while you're in the middle of a forEach call, then yes, it is thread-safe.
  • If you want the map to be unmodifiable while forEach is in progress such that other threads are blocked or error out if they attempt to modify it then no, it is not.

The API documentation says:

However, even though all operations are thread-safe, retrieval operations do not entail locking, and there is not any support for locking the entire table in a way that prevents all access.

...

Similarly, Iterators, Spliterators and Enumerations return elements reflecting the state of the hash table at some point at or since the creation of the iterator/enumeration. They do not throw ConcurrentModificationException.... Bear in mind that the results of aggregate status methods ... are typically useful only when a map is not undergoing concurrent updates in other threads. Otherwise the results of these methods reflect transient states that may be adequate for monitoring or estimation purposes, but not for program control.

Ensure to get all values of `ConcurrentHashMap` when iterating over it while other threads put elements

The documentation for ConcurrentHashMap.size() doesn't provide any guarantees about visibility effects, it delegates to the following method which does the actual counting

final long sumCount() {
CounterCell[] as = counterCells; CounterCell a;
long sum = baseCount;
if (as != null) {
for (int i = 0; i < as.length; ++i) {
if ((a = as[i]) != null)
sum += a.value;
}
}
return sum;
}

Presumably as a side effect it makes all the elements visible in your code, but that's not something you should rely on (at least unless you understand the inner workings of ConcurrentHashMap, I don't).

The purpose of ConcurrentHashMap is to provide thread-safe insertion and retrieval, but I suppose getting iteration to work in a reliable way is hard or impossible. I'm not aware of any standard Maps that would work as a replacement either, another concurrent map ConcurrentSkipListMap also says that its iterators and spliterators are weakly consistent.

Does Set of ConcurrentHashMap is thread safe in foreach?

Yes, the keySet view is thread safe, the newKeySet in java >=8 is equivalent to this java 7 form:

for java <= 7

ConcurrentHashMap c = ...;
Set threadSafeSet = c.keySet();

for java >=8

Set threadSafeSet =  ConcurrentHashMap.newKeySet();

ConcurrentHashMap remove() using thread A while iterating using thread B

Well, remove() clones HashEntry elements up to removed element, not modifies old ones. So you get

B*->A*->D->E in bucket, but original

A->B->C-^ sequence is not touched.

You can be sure that A.equals(A*) == false, even though they will have equal keys and equal values. But that's not a problem for iterator as it simply uses already aquired entry A to move on.

P.S. ConcurrentHashMap uses locks on bucket level for modifications. It's not lock-free.

is ConcurrentHashMap.put() always Thread-Safe? if so, then why it is not working correctly?

The problem is not with the hash map itself but the index. You are using ++ which isn’t an atomic command and thus isn’t thread safe. When you are using synchronized word on the function it syncs the index too and solves the problem.



Related Topics



Leave a reply



Submit