Java
Multi-threading
Safe Publication
Concurrency
Thread Safety

Java multi-threading Safe Publication

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Safe publication in Java means making an object visible to other threads in a way that guarantees they observe a fully constructed and correctly initialized state. Without safe publication, another thread may see stale values, partially initialized fields, or state that appears impossible from a single-threaded perspective.

This is a Java Memory Model issue, not just a style preference. The object may be constructed correctly, but if it is published incorrectly, other threads are not guaranteed to see that construction.

What Unsafe Publication Looks Like

The classic bug is storing an object into a shared field without synchronization, then reading it from another thread.

java
1class Holder {
2    int value;
3
4    Holder(int value) {
5        this.value = value;
6    }
7}
8
9class Example {
10    private Holder holder;
11
12    void init() {
13        holder = new Holder(42);
14    }
15
16    Holder get() {
17        return holder;
18    }
19}

This looks harmless, but without a happens-before relationship, another thread is not guaranteed to observe the write safely.

Common Safe Publication Mechanisms

Java gives several reliable ways to publish safely:

  • storing the reference in a final field during construction
  • publishing through a volatile field
  • publishing under the same lock used for reading
  • publishing from a static initializer
  • publishing through thread-safe containers such as ConcurrentHashMap

Each of these creates the visibility guarantees that plain unsynchronized sharing lacks.

Example with volatile

If a reference is written to a volatile field, later readers of that field see the initialized object state.

java
1class Config {
2    private final String name;
3
4    Config(String name) {
5        this.name = name;
6    }
7
8    String getName() {
9        return name;
10    }
11}
12
13class Service {
14    private volatile Config config;
15
16    void load() {
17        config = new Config("prod");
18    }
19
20    Config current() {
21        return config;
22    }
23}

This is a common pattern for configuration reloads or lazily initialized shared state.

Final Fields Help, but Publication Still Matters

final fields have special visibility guarantees after correct construction. That is why immutable objects are so attractive in concurrent code.

java
1final class UserProfile {
2    private final String id;
3    private final int level;
4
5    UserProfile(String id, int level) {
6        this.id = id;
7        this.level = level;
8    }
9
10    String getId() { return id; }
11    int getLevel() { return level; }
12}

However, immutability does not give you permission to publish the reference through a broken sharing mechanism. The publication step still must be safe.

Safe Publication Through Initialization or Locks

Static initialization is inherently safe because class initialization has the right memory barriers.

java
class Registry {
    static final UserProfile DEFAULT_USER = new UserProfile("guest", 0);
}

Locks also work because unlocking in one thread and locking in another creates a happens-before relationship.

java
1class Cache {
2    private UserProfile profile;
3
4    synchronized void set(UserProfile p) {
5        profile = p;
6    }
7
8    synchronized UserProfile get() {
9        return profile;
10    }
11}

This is slower than immutable one-time publication in some scenarios, but it is correct and easy to reason about.

Common Pitfalls

  • Assuming object construction alone makes the object safe to share across threads.
  • Confusing thread-safe mutation with safe publication of the initial reference.
  • Relying on immutable fields but then publishing the object through an unsynchronized shared variable.
  • Using double-checked locking without volatile on the shared reference.
  • Fixing visibility for writers but not for readers, which leaves no full happens-before chain.

Summary

  • Safe publication means other threads are guaranteed to see a fully initialized object.
  • Plain unsynchronized sharing does not provide that guarantee.
  • Reliable publication mechanisms include final, volatile, synchronization, static initialization, and thread-safe containers.
  • Immutable objects are easier to publish safely, but the publication step still matters.
  • Think in terms of happens-before relationships, not just object construction order.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.