In a multi-threaded application, is there any scenario in which it is better to use a HashMap with synchronization when needed, than to use a ConcurrentHashMap?
Specifically, I am thinking of an application where the map is initialized like this:
Map<String,String> map = new HashMap<>();
Each thread accesses the map only to update it and immediately convert it to string, so the only synchronized block is:
synchronized(map) {
map.put(key,value);
StringBuilder sb = new StringBuilder();
for (String k: map.keySet())
sb.append("("+k+","+map.get(k)+")");
}
In this case, will it be safer to change the initialization to:
Map<String,String> map = new ConcurrentHashMap<>();
and drop the "synchronized"?
The question is what is important for you from the application point of view. If you want to have a string conversion of the map synchronized with the state after the put method invocation, your code is the only solution.
If we say that a state of the map before yours synchronized block it this:
and you invoke your piece of code with
key = "key3" and value="value3"
the synchronized block ensures the string conversion will be
(key1,value1)(key2,value2)(key3,value3)
If you remove synchronized block and change map to some synchronized implementation the only synchronized part will be put itself. So the timeline of method invoke can be in some cases like:
So Thread1 converts incorrect state because Thread2 was fast enough to put a new entry before Thread1 invoke string conversion.
Generally synchronized implementation of any collection is useful only in cases you want methods of collection as atomic operations. If you need cooperation of more methods in the same state of collection you have to synchronize them from outside every time.
The class documentation says this:
For aggregate operations such as putAll and clear, concurrent retrievals may reflect insertion or removal of only some entries. 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.
So if you care about these cases in an atomic way, external synchronization might be what u need.
And it seems you do care about this, since you do keySet()
, this is not atomic, other entries might be added or removed while you are doing your for loop
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With