Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is changing the value of a Map an atomic operation?

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?

like image 249
Olivier Twist Avatar asked Mar 11 '12 21:03

Olivier Twist


People also ask

Is ConcurrentHashMap Atomic?

Atomic operations: All operations on the ConcurrentHashMap are atomic, which means you can safely perform concurrent data access.

What will happen if we put two values with the same key in map?

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.

How do you atomically update a value in ConcurrentHashMap?

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.


2 Answers

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!

like image 162
templatetypedef Avatar answered Sep 27 '22 19:09

templatetypedef


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.

like image 25
Jeffrey Avatar answered Sep 27 '22 19:09

Jeffrey