PrepAhead
Start free
← All posts

Java memory model quiz (15 questions)

June 5, 2026

  • Java
  • JVM
  • Concurrency
  • Backend

This set goes past API memorization and into the reasoning interviewers use to separate surface-level concurrency knowledge from real understanding. The key theme is not just which keyword to choose, but what visibility and ordering guarantee that choice creates.

If these questions still feel slippery, practice drawing the write-read relationships explicitly. Once you can explain the happens-before edge in plain language, most memory model interview questions become much easier to defend out loud.

Question 1

One thread sets ready = true and another spins until ready becomes true. Without synchronization or volatile, what is the safest assumption?

Pick an answer to see if you are correct
Reveal answer

Answer

The reader may never observe the update - The safest assumption is that the reader may never observe the update in a timely way, or at all from the program's point of view.

Explanation

Without a happens-before relationship, the Java Memory Model does not guarantee visibility of one thread's write to another thread's read. CPU caches, compiler optimizations, and instruction reordering can all contribute to stale observations.

Common interview notes

A classic follow-up is how declaring ready as volatile changes the guarantee.

Question 2

What does a happens-before relationship primarily guarantee?

Pick an answer to see if you are correct
Reveal answer

Answer

Earlier writes become visible to a later read that is ordered after them - A happens-before relationship guarantees visibility and ordering for memory effects between the related actions.

Explanation

If action A happens-before action B, then the writes visible at A are guaranteed to be visible to B, subject to the normal rules of the memory model. This is why synchronization, volatile, thread start, thread join, and final-field rules matter.

Common interview notes

Good answers mention that happens-before is broader than locking alone and includes several language-level ordering edges.

Question 3

Which statement about volatile is correct?

Pick an answer to see if you are correct
Reveal answer

Answer

It provides visibility and ordering guarantees for reads and writes of that variable - volatile provides visibility and certain ordering guarantees for reads and writes of that variable.

Explanation

A volatile write is visible to later volatile reads of the same variable, and the memory model prevents some reorderings around those accesses. It does not make compound actions such as increment atomic, and it does not replace mutual exclusion for larger critical sections.

Common interview notes

Interviewers often ask you to compare volatile with synchronized and atomic classes in one concrete scenario.

Question 4

Why can instruction reordering be legal in correctly synchronized Java programs?

Pick an answer to see if you are correct
Reveal answer

Answer

Because the JVM may reorder operations as long as single-thread semantics and memory model guarantees are preserved - Reordering can be legal as long as the observable behavior remains valid under the Java Memory Model.

Explanation

Compilers and processors may change execution order for performance if the resulting program still respects the guarantees required by synchronization, volatile, final-field semantics, and as-if-serial behavior for a single thread. Unsafely shared state is where those optimizations become visible as bugs.

Common interview notes

A strong answer separates source order, execution order, and visibility order instead of treating them as identical.

Question 5

You publish an immutable configuration object through a properly constructed final field reference. Why is that attractive for concurrency?

Pick an answer to see if you are correct
Reveal answer

Answer

final fields have special visibility guarantees after safe construction - final fields have special visibility guarantees once the object is constructed safely and then published.

Explanation

The memory model gives stronger guarantees for final fields than for ordinary mutable fields, which is one reason immutable objects are so useful in concurrent code. However, the object still must not leak this during construction, and referenced mutable state can still be a problem.

Common interview notes

Follow-ups often ask whether final on a reference also makes the referenced object immutable. It does not.

Question 6

After threadA calls threadB.start, which statement is true?

Pick an answer to see if you are correct
Reveal answer

Answer

Actions in threadA before start happen-before actions in threadB after it begins - Actions in the parent thread before start happen-before actions in the started thread after it begins.

Explanation

Thread start creates an ordering edge in the Java Memory Model. That is why state prepared before calling start can be safely observed by the new thread without extra publication steps, assuming the object graph itself is not being mutated unsafely later.

Common interview notes

The symmetric follow-up is usually about what join guarantees on the way back.

Question 7

What does threadA.join on threadB give threadA after join returns successfully?

Pick an answer to see if you are correct
Reveal answer

Answer

It guarantees threadA can see the effects of threadB's completed actions - join establishes that threadA can observe the memory effects of threadB's completed actions after the join returns.

Explanation

Thread completion and successful join form another happens-before edge. This is why join is not only a coordination tool for waiting, but also a visibility tool for results written before the worker thread finished.

Common interview notes

A strong answer connects join to both liveness and visibility instead of treating it as mere blocking.

Question 8

Which pattern is unsafe without volatile or synchronization in a lazily initialized singleton?

Pick an answer to see if you are correct
Reveal answer

Answer

Double-checked locking with a non-volatile instance field - Double-checked locking is unsafe when the instance field is not volatile.

Explanation

Without volatile, another thread can observe a reference to a partially constructed object due to reordering between allocation, assignment, and initialization. Modern Java supports double-checked locking only when the shared instance reference is volatile.

Example

class Holder {
  private static volatile Holder instance;
}

Common interview notes

This is a classic senior-level question. Interviewers usually want you to explain partial construction, not just recite the rule.

Question 9

Why is publishing this from a constructor considered dangerous?

Pick an answer to see if you are correct
Reveal answer

Answer

Other threads can observe the object before construction has finished - Publishing this from a constructor is dangerous because another thread may observe the object before initialization is complete.

Explanation

Escaping this during construction breaks the assumptions behind safe initialization and final-field semantics. Listeners, thread starts, and callbacks registered from constructors are common ways this bug appears in practice.

Common interview notes

A good answer names at least one real escape path, such as starting a thread in the constructor or registering a listener.

Question 10

Which statement about reading one volatile field and then an ordinary field written before that volatile write is most accurate?

Pick an answer to see if you are correct
Reveal answer

Answer

The volatile read can make prior writes by the publishing thread visible - A volatile read can make earlier writes performed before the corresponding volatile write visible to the reading thread.

Explanation

This is why volatile often works as a publication flag. If a writer fully initializes state and then writes ready = true to a volatile field, a reader that sees ready as true is also guaranteed to observe the prior writes that happened before that volatile write.

Common interview notes

The interview usually turns here toward publication patterns such as ready flags and immutable snapshots.

Question 11

Which tool is the best default when multiple fields must change together under one invariant?

Pick an answer to see if you are correct
Reveal answer

Answer

synchronized or an explicit lock - synchronized or an explicit lock is the best default when correctness depends on multiple fields changing together.

Explanation

Memory visibility alone is not enough if readers must never observe a half-updated state. Locks provide mutual exclusion plus ordering and visibility, which is what composite invariants usually require.

Common interview notes

A common follow-up is to ask for an example where volatile is correct for a flag but wrong for a state machine.

Question 12

If a reference to a mutable object is stored in a final field, what is true?

Pick an answer to see if you are correct
Reveal answer

Answer

The reference cannot change, but the object it points to may still mutate - final fixes the reference, not the mutability of the object behind that reference.

Explanation

final helps with initialization safety for the reference itself, but deep immutability still depends on the object graph. If the referenced object exposes mutable state without synchronization, that state can still create race conditions.

Common interview notes

Strong answers distinguish shallow immutability from deep immutability immediately.

Question 13

Which publication approach is generally safe for sharing configuration snapshots across threads?

Pick an answer to see if you are correct
Reveal answer

Answer

Publish a fully built immutable object through a volatile or final-backed safe path - Publishing a fully built immutable snapshot through a safe publication path is generally a strong approach.

Explanation

Immutable snapshots reduce coordination needs because readers do not modify the shared object. Pairing immutability with safe publication, such as static initialization, volatile publication, or lock-protected assignment, gives predictable visibility.

Common interview notes

This is a great place to mention copy-on-write style designs or replacing whole objects instead of mutating them in place.

Question 14

What is the most accurate reason a busy-spin loop on a non-volatile field is risky?

Pick an answer to see if you are correct
Reveal answer

Answer

The JVM may hoist or cache the read so the loop never observes updates - The loop is risky because the read may be optimized or cached in a way that prevents timely visibility of another thread's write.

Explanation

Without a memory barrier, the compiler or processor may treat the value as effectively unchanged from the looping thread's perspective. This is the same core visibility issue that makes plain flags unsafe for inter-thread signaling.

Common interview notes

Interviewers may ask for safer alternatives such as volatile, locks, latches, or higher-level concurrency utilities.

Question 15

Which statement about synchronized blocks and the memory model is correct?

Pick an answer to see if you are correct
Reveal answer

Answer

Unlocking a monitor happens-before a later lock of the same monitor - Unlocking a monitor happens-before a later lock of the same monitor.

Explanation

That ordering rule is why synchronized protects both mutual exclusion and memory visibility. A thread entering the synchronized block after another thread exits the same monitor is guaranteed to observe the writes that were made inside the earlier critical section.

Common interview notes

Good answers connect the rule back to a concrete bug class such as stale reads disappearing once access is consistently synchronized.

Full answer key

Review every answer in one place, with explanations and interview tips below.

1. One thread sets ready = true and another spins until ready becomes true. Without synchronization or volatile, what is the safest assumption?

Answer summary

The reader may never observe the update — The safest assumption is that the reader may never observe the update in a timely way, or at all from the program's point of view.

Without a happens-before relationship, the Java Memory Model does not guarantee visibility of one thread's write to another thread's read. CPU caches, compiler optimizations, and instruction reordering can all contribute to stale observations.

Interview tip: A classic follow-up is how declaring ready as volatile changes the guarantee.

2. What does a happens-before relationship primarily guarantee?

Answer summary

Earlier writes become visible to a later read that is ordered after them — A happens-before relationship guarantees visibility and ordering for memory effects between the related actions.

If action A happens-before action B, then the writes visible at A are guaranteed to be visible to B, subject to the normal rules of the memory model. This is why synchronization, volatile, thread start, thread join, and final-field rules matter.

Interview tip: Good answers mention that happens-before is broader than locking alone and includes several language-level ordering edges.

3. Which statement about volatile is correct?

Answer summary

It provides visibility and ordering guarantees for reads and writes of that variable — volatile provides visibility and certain ordering guarantees for reads and writes of that variable.

A volatile write is visible to later volatile reads of the same variable, and the memory model prevents some reorderings around those accesses. It does not make compound actions such as increment atomic, and it does not replace mutual exclusion for larger critical sections.

Interview tip: Interviewers often ask you to compare volatile with synchronized and atomic classes in one concrete scenario.

4. Why can instruction reordering be legal in correctly synchronized Java programs?

Answer summary

Because the JVM may reorder operations as long as single-thread semantics and memory model guarantees are preserved — Reordering can be legal as long as the observable behavior remains valid under the Java Memory Model.

Compilers and processors may change execution order for performance if the resulting program still respects the guarantees required by synchronization, volatile, final-field semantics, and as-if-serial behavior for a single thread. Unsafely shared state is where those optimizations become visible as bugs.

Interview tip: A strong answer separates source order, execution order, and visibility order instead of treating them as identical.

5. You publish an immutable configuration object through a properly constructed final field reference. Why is that attractive for concurrency?

Answer summary

final fields have special visibility guarantees after safe construction — final fields have special visibility guarantees once the object is constructed safely and then published.

The memory model gives stronger guarantees for final fields than for ordinary mutable fields, which is one reason immutable objects are so useful in concurrent code. However, the object still must not leak this during construction, and referenced mutable state can still be a problem.

Interview tip: Follow-ups often ask whether final on a reference also makes the referenced object immutable. It does not.

6. After threadA calls threadB.start, which statement is true?

Answer summary

Actions in threadA before start happen-before actions in threadB after it begins — Actions in the parent thread before start happen-before actions in the started thread after it begins.

Thread start creates an ordering edge in the Java Memory Model. That is why state prepared before calling start can be safely observed by the new thread without extra publication steps, assuming the object graph itself is not being mutated unsafely later.

Interview tip: The symmetric follow-up is usually about what join guarantees on the way back.

7. What does threadA.join on threadB give threadA after join returns successfully?

Answer summary

It guarantees threadA can see the effects of threadB's completed actions — join establishes that threadA can observe the memory effects of threadB's completed actions after the join returns.

Thread completion and successful join form another happens-before edge. This is why join is not only a coordination tool for waiting, but also a visibility tool for results written before the worker thread finished.

Interview tip: A strong answer connects join to both liveness and visibility instead of treating it as mere blocking.

8. Which pattern is unsafe without volatile or synchronization in a lazily initialized singleton?

Answer summary

Double-checked locking with a non-volatile instance field — Double-checked locking is unsafe when the instance field is not volatile.

Without volatile, another thread can observe a reference to a partially constructed object due to reordering between allocation, assignment, and initialization. Modern Java supports double-checked locking only when the shared instance reference is volatile.

class Holder {
  private static volatile Holder instance;
}

Interview tip: This is a classic senior-level question. Interviewers usually want you to explain partial construction, not just recite the rule.

9. Why is publishing this from a constructor considered dangerous?

Answer summary

Other threads can observe the object before construction has finished — Publishing this from a constructor is dangerous because another thread may observe the object before initialization is complete.

Escaping this during construction breaks the assumptions behind safe initialization and final-field semantics. Listeners, thread starts, and callbacks registered from constructors are common ways this bug appears in practice.

Interview tip: A good answer names at least one real escape path, such as starting a thread in the constructor or registering a listener.

10. Which statement about reading one volatile field and then an ordinary field written before that volatile write is most accurate?

Answer summary

The volatile read can make prior writes by the publishing thread visible — A volatile read can make earlier writes performed before the corresponding volatile write visible to the reading thread.

This is why volatile often works as a publication flag. If a writer fully initializes state and then writes ready = true to a volatile field, a reader that sees ready as true is also guaranteed to observe the prior writes that happened before that volatile write.

Interview tip: The interview usually turns here toward publication patterns such as ready flags and immutable snapshots.

11. Which tool is the best default when multiple fields must change together under one invariant?

Answer summary

synchronized or an explicit lock — synchronized or an explicit lock is the best default when correctness depends on multiple fields changing together.

Memory visibility alone is not enough if readers must never observe a half-updated state. Locks provide mutual exclusion plus ordering and visibility, which is what composite invariants usually require.

Interview tip: A common follow-up is to ask for an example where volatile is correct for a flag but wrong for a state machine.

12. If a reference to a mutable object is stored in a final field, what is true?

Answer summary

The reference cannot change, but the object it points to may still mutate — final fixes the reference, not the mutability of the object behind that reference.

final helps with initialization safety for the reference itself, but deep immutability still depends on the object graph. If the referenced object exposes mutable state without synchronization, that state can still create race conditions.

Interview tip: Strong answers distinguish shallow immutability from deep immutability immediately.

13. Which publication approach is generally safe for sharing configuration snapshots across threads?

Answer summary

Publish a fully built immutable object through a volatile or final-backed safe path — Publishing a fully built immutable snapshot through a safe publication path is generally a strong approach.

Immutable snapshots reduce coordination needs because readers do not modify the shared object. Pairing immutability with safe publication, such as static initialization, volatile publication, or lock-protected assignment, gives predictable visibility.

Interview tip: This is a great place to mention copy-on-write style designs or replacing whole objects instead of mutating them in place.

14. What is the most accurate reason a busy-spin loop on a non-volatile field is risky?

Answer summary

The JVM may hoist or cache the read so the loop never observes updates — The loop is risky because the read may be optimized or cached in a way that prevents timely visibility of another thread's write.

Without a memory barrier, the compiler or processor may treat the value as effectively unchanged from the looping thread's perspective. This is the same core visibility issue that makes plain flags unsafe for inter-thread signaling.

Interview tip: Interviewers may ask for safer alternatives such as volatile, locks, latches, or higher-level concurrency utilities.

15. Which statement about synchronized blocks and the memory model is correct?

Answer summary

Unlocking a monitor happens-before a later lock of the same monitor — Unlocking a monitor happens-before a later lock of the same monitor.

That ordering rule is why synchronized protects both mutual exclusion and memory visibility. A thread entering the synchronized block after another thread exits the same monitor is guaranteed to observe the writes that were made inside the earlier critical section.

Interview tip: Good answers connect the rule back to a concrete bug class such as stale reads disappearing once access is consistently synchronized.

Try each question on your own, then open "Reveal answer" for the full write-up. For tailored practice and Check feedback on open-ended responses, use PrepAhead in the app - not on blog pages.