I was wondering if synchronization or using a concurrent class is necessary, or conversely is it thread safe to use a non concurrent class and do no synchronization on a map in a multi threaded environment, if the only modification to the map is changing the values of the map.
The reason I ask this is the HashMap ( and other non concurrent maps documentation ) have this comment:
Note that this implementation is not synchronized. If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the map.
Which makes me believe if the modification is not structural (i.e. There is no added or deleted) I should be able to update the (non concurrent) map sans synchronization.
Am I reading this correct? i.e. Is Updating of a value in a map an atomic process?
Atomic operations: All operations on the ConcurrentHashMap are atomic, which means you can safely perform concurrent data access.
However, none of the existing Java core Map implementations allow a Map to handle multiple values for a single key. As we can see, if we try to insert two values for the same key, the second value will be stored, while the first one will be dropped.
The compute(Key, BiFunction) method of ConcurrentHashMap class is used to compute a mapping for the specified key and its current mapped value (or null if there is no current mapping is found). This method is used to atomically update a value for given key in ConcurrentHashMap.
Updating a map value is not an atomic process. However, having multiple different threads each try to modify map values concurrently will not result in very strange exceptions or errors due to concurrency errors. For example, you won't cause one of the key/value pairs to disappear, or delete random elements out of the map.
However, the updates made by one thread when updating a key/value pair will not necessarily be visible to other threads unless there is some other synchronization going on (for example, if the values are things like AtomicIntegers
). On top of this, there's no guarantee that the thread will even see its own updates, since they might get clobbered by some other thread.
Hope this helps!
Putting something in a HashMap
is not an atomic operation:
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
It may be worthwhile to wrap your HashMap
with Collections#synchronizedMap
.
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