Java concurrency: is final field (initialized in constructor) thread-safe?

Solution 1:

As already pointed out it's absolutely thread-safe, and final is important here due to its memory visibility effects.

Presence of final guarantees that other threads would see values in the map after constructor finished without any external synchronization. Without final it cannot be guaranteed in all cases, and you would need to use safe publication idioms when making newly constructed object available to other threads, namely (from Java Concurrency in Practice):

  • Initializing an object reference from a static initializer;
  • Storing a reference to it into a volatile field or AtomicReference;
  • Storing a reference to it into a final field of a properly constructed object; or
  • Storing a reference to it into a field that is properly guarded by a lock.

Solution 2:

Yes it is. There is no way to modify the reference aMap itself, or add to the map after the constructor (barring reflection).

If you expose aMap it will not be, because two threads could then modify the map at the same time.

You could improve your class by making aMap unmodifiable via Collections.unmodifiableCollection or Collections.unmodifiableMap.

Solution 3:

Guava has immutable classes for making this sort of thing easier and guaranteed immutable:

private final ImmutableMap<String, String> aMap = ImmutableMap.of(
    "1", "a",
    "2", "b",
    "3", "c");

Solution 4:

Yes it is, provided this is the entire class definition and not a snippet thereof.

The key fact is that there is no way the contents of aMap can be modified post-construction.

Solution 5:

This class has no concurrency issue cause you expose only a get method. If you add some method that modify the map you have to mark this method as synchronized.