In the doc, it says
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.)
It seems indicating that changing the value associated with a key that an instance already contains does not need external synchronization. But I think it's not thread safe. right?
For thread visibility purposes yes, you'll need external syncing if you have two threads that communicate using the map. But unsynchronized structural changes have a chance of corrupting the map completely (imagine when 2 threads put a new mapping and both start to rehash the map), whereas changing a mapped value will have less dramatic effects.
Even with only one thread doing structural modifications it's problematic if the backing array is grown/rehashed. Other threads using the same array (or the old one, if the array is grown) can encounter lost updates (thread puts value in the old array instead of new array), disappearing mappings (thread puts value in the array, while another thread is rehashing the same array, value gets put in the wrong bucket) and so on.
So when is it safe to not synchronize? Almost never. A safe situation would be a pre-built map with threads only accessing "their" entries, like
thread1: map.get("A");
thread2: map.put("B", "1"); // Assume "B" was in the map already
thread3: map.get("C");
No problems because no structural changes and threads are not sharing keys. As soon as you start sharing keys between threads, you can get race conditions and visibility issues. If you introduce structural changes, those visibility issues can result in data loss in the map.
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