ProgrammingBackend Developer

Explain what safe publication is in Java, why it is needed in multithreading, and what ways exist to ensure it.

Pass interviews with Hintsage AI assistant

Answer

Safe Publication is the guaranteed safe distribution of an object between threads: if one thread creates and initializes an object, another thread will always see the fully constructed object, not its partially initialized state.

Without safe publication, you can encounter a race condition: one thread sees an uninitialized part of the object even if the constructor has finished execution.

Ways to ensure safe publication:

  • Use final fields — their value is guaranteed to be visible to other threads after the constructor.
  • Publish the object through a volatile variable or AtomicReference.
  • Publish the object through thread-safe containers (e.g., collections from java.util.concurrent).
  • Use synchronized when creating and reading the object.

Example (unsafe):

public class Holder { private int n; public Holder(int n) { this.n = n; } } Holder holder; void publish() { holder = new Holder(42); } // Safety is not guaranteed

Partially constructed objects may be visible!

Example (safe):

volatile Holder holder; void publish() { holder = new Holder(42); } // Reading holder will also be safe

Trick question

If all fields in an object are final, does this guarantee safe publication always?

Answer: No, only if the reference to the new object is published before the end of the constructor. If the reference goes to other threads before the constructor completes, the fields may not be fully initialized. You should avoid publishing this or references to incompletely constructed objects during the execution of the constructor.

Example (dangerous!):

public class PublishEscape { public static PublishEscape instance; public PublishEscape() { instance = this; // Bad! this is published before the end of the constructor } }

History

A developer assigned a reference to a Service instance to a field accessible via static before the constructor was complete. As a result, another thread received a partially-constructed object, causing unpredictable behavior in production.


History

In a web application, singleton objects were created without additional synchronization. Under load, some threads received null or incorrectly initialized fields, leading to Intermittent NullPointerException.


History

In a library, a regular List was used for cache between threads — safe publication was absent, and initialization did not guarantee visibility to new threads. Consequently, the cache operated chaotically, violating data integrity.