3

Concurrent updates to non-synchronized HashMap can obviously cause a livelock or other data corruptions; to avoid this, one should use the concurrent version or implement a synchronization mechanism.

Can concurrent calls to HashMap.get() change the state of the HashMap, like rehashing?

Update:

Some commenters wondered about the practical aspects of the question, besides the theoretical joy of nitpicking data structure behavior.

If get() does not change the state of the HashMap (and can't cause a livelock for another reaseon), than a single thread can create a HashMap in advance, and then many threads can read from it concurrently. If concurrent reading isn't safe, we need ConcurrentHashMap for every multi-threaded access, regardless of type.

Adam Matan
  • 107,447
  • 124
  • 346
  • 512

4 Answers4

4

From the java docs:

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 implies that concurrent get() are fine and will not cause change of state.

In addition, you can always have a look at the source for more information on how it is built.

amit
  • 166,614
  • 24
  • 210
  • 314
  • +1 I could not find a reference ;-) Different map implementations might define what a structural modification is differently (cf linkedhashmap) but in the case of hashmap, `get` is not a structural modification. – assylias Nov 14 '12 at 07:52
  • +1 Logically, the fact that at having at least one writer thread requires synchronization does not imply that having just reader threads doesn't require it. – Adam Matan Nov 16 '12 at 07:57
1

Javadocs generally define what is considered a structural modification of the map. HashMap states that get is not an operation that will cause a structural modification.

However, other map implementations behave differently. For example, a LinkedHashMap can use access order in which case get is a structural modification:

In access-ordered linked hash maps, merely querying the map with get is a structural modification.

assylias
  • 297,541
  • 71
  • 621
  • 741
0

If you what to know what happens inside HashMap.get() (which is a specific implementation of the Map interface), you can read the code of the implementation.

But for all purposes you should NOT care about how the function is implemented and what it does! The only important thing is for the function to attain itself to its contract (API + class/function javadocs). The implementation can change in the future, so depending on it is bad practice.

vainolo
  • 6,681
  • 3
  • 20
  • 45
  • 1
    But this is not an implementation specific issue. It is important to know if one can access a `HashMap` for `get()`s from multimple threads - or should it be synchronized. I can think of many uses for it. – amit Nov 14 '12 at 07:54
  • If you are going to use your `Map` in a concurrent environment, why not use concurrent collections instead: [`ConcurrentHashMap`](http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ConcurrentHashMap.html) – vainolo Nov 14 '12 at 08:00
  • 1
    Because if you only need concurrent reads - avoiding the overhead of using a `ConcurrentHashMap` might be a good thing. – amit Nov 14 '12 at 08:01
  • Don't optimize for performance, optimize for correctness. Then if you have performance issues, find them and fix them. Finding and debugging bugs in multithreaded programs is **hard**, so why take the chance? And if you use `Map` interface, you will also be able to change the implementation in the future seamlesly – vainolo Nov 14 '12 at 08:05
0

Only calling get() is surely not going to cause any problem as you are saying. However, concurrent un-synchronized updates may surely cause so. In get() method, it's only going to call hashcode() method on members until a match has been found. No update will be done in this case.

Sumit Desai
  • 1,396
  • 8
  • 19