[{"data":1,"prerenderedAt":134},["ShallowReactive",2],{"qa-\u002Fjava\u002Fconcurrency\u002Fvolatile-memory-model":3},{"page":4,"siblings":114,"blog":131},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":20,"path":21,"questions":22,"questionsCount":104,"related":105,"seo":106,"seoDescription":107,"stem":108,"subtopic":109,"topic":110,"topicSlug":111,"updated":112,"__hash__":113},"qa\u002Fjava\u002Fconcurrency\u002Fvolatile-memory-model.md","Volatile Memory Model",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"hard","md","Java","java",{},true,5,"\u002Fjava\u002Fconcurrency\u002Fvolatile-memory-model",[23,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100],{"id":24,"difficulty":25,"q":26,"a":27},"visibility-problem","medium","What is the visibility problem in multithreaded Java?","Without synchronization, there is **no guarantee** that a write made by one\nthread becomes visible to another. Each thread may keep a value in a **CPU\nregister or cache**, or the compiler may hoist a field read out of a loop, so a\nthread can read a **stale** copy forever.\n\n```java\nclass Worker {\n  boolean stop = false;   \u002F\u002F NOT volatile\n\n  void run() {\n    while (!stop) { }     \u002F\u002F may loop FOREVER — stop is cached\n  }\n  void shutdown() { stop = true; } \u002F\u002F another thread sets it\n}\n```\n\nThe `while (!stop)` loop can spin indefinitely even after `shutdown()` runs,\nbecause the reading thread never re-reads `stop` from main memory. Marking\n`stop` **`volatile`** fixes it. This is the canonical motivation for both\n`volatile` and the Java Memory Model.\n",{"id":29,"difficulty":14,"q":30,"a":31},"what-is-jmm","What is the Java Memory Model and why does it exist?","The **Java Memory Model (JMM)** is the part of the language spec that defines\n**which writes a thread is guaranteed to see** and **what reorderings are\nlegal**. It exists because real hardware and compilers aggressively optimize —\nCPU caches, store buffers, out-of-order execution, and JIT reordering — so\nwithout rules, multithreaded behavior would differ per CPU and be impossible to\nreason about.\n\nThe JMM defines an abstract relation called **happens-before**: if action A\nhappens-before action B, then A's effects are visible to B. Anything *not*\nordered by happens-before may be reordered or seen stale. So the JMM doesn't\npromise a single global order of operations — it promises a **minimum set of\nguarantees** (via `volatile`, `synchronized`, `final`, thread start\u002Fjoin) that\nportable concurrent code can rely on across JVMs and hardware.\n",{"id":33,"difficulty":14,"q":34,"a":35},"happens-before","What is the happens-before relationship?","**Happens-before** is the JMM's ordering guarantee: if A *happens-before* B, then\neverything A wrote is visible to B, and A appears to execute before B. The main\nsources of happens-before edges are:\n\n| Rule | Edge |\n| ---- | ---- |\n| **Program order** | each action happens-before later actions *in the same thread* |\n| **Monitor lock** | unlocking a monitor happens-before a later lock of the *same* monitor |\n| **Volatile** | a write to a volatile field happens-before every later read of it |\n| **Thread start** | `t.start()` happens-before any action in the started thread |\n| **Thread join** | every action in a thread happens-before another thread's `t.join()` return |\n| **Transitivity** | if A hb B and B hb C, then A hb C |\n\nWithout a happens-before edge between two threads' actions, the JMM gives **no\nvisibility or ordering guarantee** — that's the heart of every concurrency bug.\n",{"id":37,"difficulty":25,"q":38,"a":39},"volatile-guarantees","What does the volatile keyword guarantee?","`volatile` provides two things: **visibility** and **ordering**. A write to a\nvolatile field is immediately flushed so it's visible to every thread, and a\nread always fetches the latest value from main memory (never a cached copy). It\nalso establishes a **happens-before** edge: a volatile write happens-before any\nlater volatile read of that field.\n\n```java\nvolatile boolean ready = false;\nint data;\n\n\u002F\u002F writer thread\ndata = 42;          \u002F\u002F ordinary write\nready = true;       \u002F\u002F volatile write — publishes data too\n\n\u002F\u002F reader thread\nif (ready) {        \u002F\u002F volatile read\n  use(data);        \u002F\u002F guaranteed to see 42\n}\n```\n\nBecause the volatile write of `ready` happens-before the read, the *ordinary*\nwrite to `data` that preceded it is also visible. **Rule of thumb:** `volatile`\nmakes a single field a safe, lock-free flag — and piggybacks the writes before\nit.\n",{"id":41,"difficulty":14,"q":42,"a":43},"volatile-not-atomic","Why doesn't volatile make count++ thread-safe?","Because `volatile` guarantees **visibility, not atomicity**, and `count++` is a\n**compound action**: read, add one, write back. Two threads can both read the\nsame value, both increment it, and both write back the same result — a lost\nupdate — even though every individual read and write sees fresh memory.\n\n```java\nvolatile int count = 0;\ncount++;   \u002F\u002F really: int tmp = count; tmp = tmp + 1; count = tmp;\n```\n\nVolatile makes each step visible but does **not** make the three steps\nindivisible. For atomic counters use **`AtomicInteger`** (`incrementAndGet()`),\nor guard the update with a lock. **Rule of thumb:** `volatile` is correct only\nwhen a write doesn't depend on the current value (e.g. a flag), never for\nread-modify-write.\n",{"id":45,"difficulty":14,"q":46,"a":47},"volatile-vs-synchronized","What is the difference between volatile and synchronized?","Both establish happens-before edges and fix visibility, but they solve different\nproblems:\n\n| | `volatile` | `synchronized` |\n| --- | --- | --- |\n| **Visibility** | yes (per field) | yes |\n| **Atomicity** | no | yes (the whole block) |\n| **Mutual exclusion** | no | yes — one thread at a time |\n| **Blocking** | never blocks | can block on the lock |\n| **Scope** | a single field | a block \u002F method |\n\n```java\nvolatile boolean flag;          \u002F\u002F cheap visibility for one flag\n\nsynchronized (lock) {           \u002F\u002F exclusive access + visibility\n  balance = balance - amount;   \u002F\u002F compound action made safe\n}\n```\n\nUse `volatile` when you only need one variable's *latest value* visible. Use\n`synchronized` when you need **atomic compound operations** or to protect\n**multiple related fields** together.\n",{"id":49,"difficulty":14,"q":50,"a":51},"atomicity-visibility-ordering","What is the difference between atomicity, visibility, and ordering?","These are three **distinct** concurrency concerns, and interviewers love\nseparating them:\n\n- **Atomicity** — an operation happens completely or not at all; no other thread\n  sees a half-finished state. `count++` is *not* atomic.\n- **Visibility** — a write by one thread becomes observable to another. Without\n  synchronization, writes may stay invisible (cached) indefinitely.\n- **Ordering** — the order in which operations appear to execute. Compilers and\n  CPUs may **reorder** instructions that lack a happens-before constraint.\n\n```java\nvolatile boolean v;   \u002F\u002F gives visibility + ordering, NOT atomicity\nsynchronized(l){...}   \u002F\u002F gives all three for the guarded region\n```\n\n`volatile` covers visibility and ordering; **only** locks (or atomic classes)\nadd atomicity. Picking the wrong tool because you conflated these is the classic\nmistake.\n",{"id":53,"difficulty":14,"q":54,"a":55},"instruction-reordering","What is instruction reordering and why is it allowed?","Compilers, the JIT, and CPUs may **execute instructions in a different order**\nthan written, as long as a *single thread's* result is unchanged. It's allowed\nbecause reordering enables huge optimizations (register allocation, hiding memory\nlatency, out-of-order execution).\n\n```java\nint a = 1;   \u002F\u002F these two have no dependency,\nint b = 2;   \u002F\u002F so they may be reordered freely\n```\n\nThe catch: reorderings that are invisible within one thread can be **very\nvisible to another thread**. A second thread might observe `b` set before `a`.\nThe JMM only forbids reordering across **happens-before** edges (volatile\naccesses, lock release\u002Facquire). **Rule of thumb:** within a thread you never\nnotice reordering; across threads you must create a happens-before edge to\nconstrain it.\n",{"id":57,"difficulty":25,"q":58,"a":59},"as-if-serial","What is the as-if-serial \u002F single-thread guarantee?","The **as-if-serial** semantics promise that within a **single thread**, the\nprogram behaves *as if* its statements ran in exact source order — regardless of\nhow the compiler or CPU actually reordered them. Dependencies are always\nrespected.\n\n```java\nint x = 5;\nint y = x + 1;   \u002F\u002F depends on x — can never be reordered before it\nSystem.out.println(y); \u002F\u002F always 6, no matter the optimizations\n```\n\nSo a sequential program never has to worry about reordering. The guarantee\n**only** covers one thread in isolation; the moment another thread observes the\nsame fields, as-if-serial says nothing, and you need happens-before edges. This\nis why correct single-threaded code can still be broken when shared across\nthreads.\n",{"id":61,"difficulty":25,"q":62,"a":63},"volatile-flag-pattern","What is the volatile flag pattern?","The most common correct use of `volatile`: a **one-way status flag** that one\nthread sets and others poll. Because the write\u002Fread of the flag is volatile, the\nchange is guaranteed visible, so the polling thread eventually stops.\n\n```java\nclass Service {\n  private volatile boolean running = true;\n\n  void serve() {\n    while (running) { doWork(); }   \u002F\u002F sees running=false promptly\n  }\n  void stop() { running = false; }  \u002F\u002F called from another thread\n}\n```\n\nThis works only because the operation is a **simple assignment**, not a\ncompound update, and no other shared state needs to change atomically with it.\n**Rule of thumb:** reach for the volatile flag for cancellation\u002Fshutdown\nsignals — and nothing that requires read-modify-write.\n",{"id":65,"difficulty":14,"q":66,"a":67},"double-checked-locking","Why does the double-checked-locking singleton need volatile?","Double-checked locking checks the instance twice — once without a lock, once\ninside — to avoid synchronizing on every call. Without `volatile` it is\n**broken** because `instance = new Singleton()` is not atomic: it allocates\nmemory, runs the constructor, and assigns the reference, and those steps can be\n**reordered**. Another thread could see a non-null reference to a\n*partially-constructed* object.\n\n```java\nclass Singleton {\n  private static volatile Singleton instance;   \u002F\u002F volatile is REQUIRED\n\n  static Singleton get() {\n    if (instance == null) {                 \u002F\u002F 1st check, no lock\n      synchronized (Singleton.class) {\n        if (instance == null)               \u002F\u002F 2nd check, locked\n          instance = new Singleton();       \u002F\u002F safe publish via volatile\n      }\n    }\n    return instance;\n  }\n}\n```\n\n`volatile` forbids the reordering and adds a happens-before edge, so a reader\nthat sees the reference also sees a fully built object. **Rule of thumb:** if you\nhand-write DCL, the field *must* be volatile (or just use a holder-class\nidiom instead).\n",{"id":69,"difficulty":14,"q":70,"a":71},"safe-publication","What is safe publication and how do you achieve it?","**Publishing** an object means making it visible to other threads;\n**safe publication** ensures that when another thread sees the reference, it also\nsees the object's fully-initialized state. Just storing a reference in a shared\nfield is *unsafe* — another thread may see the reference but stale field values.\n\nSafe ways to publish, per *Java Concurrency in Practice*:\n\n- Store it in a **`volatile`** field (or `AtomicReference`).\n- Store it in a **`final`** field set in a constructor.\n- Store it into a field guarded by a **lock**.\n- Initialize it from a **static initializer**.\n\n```java\nclass Holder {\n  private volatile Config config;          \u002F\u002F safe publication\n  void set(Config c) { config = c; }       \u002F\u002F readers see a complete Config\n}\n```\n\n**Rule of thumb:** never just assign a shared object to a plain field and hope —\nroute the publication through volatile, final, a lock, or a thread-safe\ncollection.\n",{"id":73,"difficulty":14,"q":74,"a":75},"final-field-freeze","What guarantees do final fields provide across threads?","`final` fields have special **freeze semantics**: when a constructor finishes,\nall `final` fields are \"frozen\", and any thread that obtains the object through a\nreference published *after* construction is guaranteed to see their correctly\ninitialized values — **without** additional synchronization.\n\n```java\nclass Point {\n  final int x, y;                 \u002F\u002F frozen at end of constructor\n  Point(int x, int y) { this.x = x; this.y = y; }\n}\n\u002F\u002F any thread seeing a Point always sees the real x and y\n```\n\nThe one caveat: this holds only if the object **doesn't leak `this`** during\nconstruction (e.g. registering a listener before the constructor returns). Final\nfields are why **immutable objects are inherently thread-safe** and can be shared\nfreely. **Rule of thumb:** make fields `final` and the object immutable, and you\nget safe sharing for free.\n",{"id":77,"difficulty":14,"q":78,"a":79},"long-double-tearing","Why can reads and writes of long and double be non-atomic?","The JMM only guarantees that reads and writes of **32-bit-or-smaller** types and\n**references** are atomic. A non-volatile `long` or `double` (64 bits) may be\nwritten as **two separate 32-bit stores**, so another thread can observe a\n**torn** value — the high half of one write combined with the low half of\nanother.\n\n```java\nlong balance;            \u002F\u002F NOT volatile — write may tear\n\u002F\u002F Thread A: balance = 0xFFFFFFFF00000000L;\n\u002F\u002F Thread B might read 0xFFFFFFFF00000000, 0x0, or a mix\n```\n\nDeclaring the field **`volatile`** makes 64-bit reads and writes atomic (and\nvisible). In practice most 64-bit JVMs write longs atomically anyway, but the\nspec doesn't require it, so portable code must use `volatile` or a lock.\n**Rule of thumb:** shared `long`\u002F`double` that multiple threads write should be\n`volatile` (or atomic) to avoid tearing.\n",{"id":81,"difficulty":14,"q":82,"a":83},"memory-barriers","What are memory barriers (fences) and how do they relate to volatile?","A **memory barrier** (or fence) is a low-level CPU\u002Fcompiler instruction that\nrestricts reordering and forces cached writes to be flushed or invalidated. The\nJMM is the *abstract* model; barriers are *how* the JVM actually implements it on\nhardware.\n\nA `volatile` access compiles to barriers around it:\n\n- A **volatile write** is preceded by a *StoreStore* barrier and followed by a\n  *StoreLoad* barrier — earlier writes can't move after it, and the write is\n  flushed.\n- A **volatile read** is followed by *LoadLoad* \u002F *LoadStore* barriers — later\n  reads can't move before it.\n\n```java\nx = 1;            \u002F\u002F ordinary write\nvolatileFlag = 2; \u002F\u002F StoreStore before, StoreLoad after — x can't cross down\n```\n\nYou almost never write barriers directly in Java (they're exposed via\n`VarHandle`); `volatile` and `synchronized` insert the right ones for you.\n",{"id":85,"difficulty":14,"q":86,"a":87},"volatile-array","Does declaring an array volatile make its elements volatile?","No. `volatile` on an **array reference** only makes the **reference** itself\nvolatile — reassigning the whole array is visible. Reads and writes of individual\n**elements** are *not* volatile and carry no visibility guarantee.\n\n```java\nvolatile int[] arr = new int[10];\narr = new int[20];   \u002F\u002F volatile: visible to other threads\narr[3] = 99;         \u002F\u002F NOT volatile — element write may be invisible\n```\n\nTo get volatile-element semantics, use **`AtomicIntegerArray`** \u002F\n`AtomicReferenceArray`, or access elements through a `VarHandle` with the right\naccess mode. **Rule of thumb:** a volatile array gives you a safe *swap* of the\narray, not safe concurrent *element* updates.\n",{"id":89,"difficulty":14,"q":90,"a":91},"volatile-compound-state","Why doesn't making fields volatile make a multi-field invariant safe?","`volatile` operates on **one field at a time**, so it can't keep **two related\nfields consistent** with each other. Even if both are volatile, another thread\ncan observe an update to one field but not yet the other, breaking the invariant.\n\n```java\nclass Range {\n  private volatile int lower = 0, upper = 10;   \u002F\u002F both volatile\n  void setLower(int v) {\n    if (v > upper) throw new IllegalArgumentException();\n    lower = v;     \u002F\u002F check-then-act: not atomic across two fields\n  }\n}\n```\n\nTwo threads calling `setLower`\u002F`setUpper` concurrently can pass the checks and\nleave `lower > upper`. Multi-field invariants need a **lock** (or an immutable\nobject swapped atomically). **Rule of thumb:** `volatile` is per-field; whenever\nan operation spans more than one variable, you need a lock.\n",{"id":93,"difficulty":25,"q":94,"a":95},"volatile-vs-atomic","When should you use an Atomic class instead of volatile?","Use `volatile` when you only need a field's writes to be **visible** and each\noperation is an independent assignment. Use an **`Atomic`** class\n(`AtomicInteger`, `AtomicReference`, …) when you need an **atomic\nread-modify-write** — increment, compare-and-set, accumulate.\n\n```java\nvolatile boolean ready;            \u002F\u002F visibility only — fine\n\nAtomicInteger seq = new AtomicInteger();\nint id = seq.incrementAndGet();    \u002F\u002F atomic RMW — volatile can't do this\n\nAtomicReference\u003CNode> head = new AtomicReference\u003C>();\nhead.compareAndSet(old, updated);  \u002F\u002F lock-free CAS update\n```\n\nAtomic classes are built on **compare-and-swap (CAS)** hardware instructions and\ngive lock-free atomicity on a single variable. **Rule of thumb:** flag →\n`volatile`; counter\u002Faccumulator\u002FCAS → `Atomic`; multiple fields → lock.\n",{"id":97,"difficulty":25,"q":98,"a":99},"synchronized-visibility","Does synchronized also provide visibility, or only mutual exclusion?","It provides **both**. People think of `synchronized` as a lock for mutual\nexclusion, but it also creates happens-before edges that guarantee visibility:\n**releasing** a monitor happens-before any subsequent **acquire** of the *same*\nmonitor. So entering a synchronized block sees all writes made before the last\nthread exited it.\n\n```java\nObject lock = new Object();\nint data;\n\nsynchronized (lock) { data = 42; }   \u002F\u002F release flushes the write\nsynchronized (lock) { use(data); }   \u002F\u002F acquire sees 42 — visibility\n```\n\nThat's why correctly synchronized code never needs `volatile` on the fields it\nguards — the lock already publishes them. The two effects (exclusion +\nvisibility) come together, but only when **both** threads synchronize on the\n**same** lock.\n",{"id":101,"difficulty":14,"q":102,"a":103},"happens-before-transitivity","How does happens-before transitivity enable safe publication?","**Transitivity** — if A happens-before B and B happens-before C, then A\nhappens-before C — is what lets a single volatile or lock edge publish a whole\ncluster of ordinary writes.\n\n```java\nint a, b;                 \u002F\u002F ordinary fields\nvolatile boolean pub;\n\n\u002F\u002F Writer\na = 1;                    \u002F\u002F (1)\nb = 2;                    \u002F\u002F (2)\npub = true;               \u002F\u002F (3) volatile write\n\n\u002F\u002F Reader\nif (pub) {                \u002F\u002F (4) volatile read\n  System.out.println(a + b); \u002F\u002F sees 3\n}\n```\n\nBy program order (1) and (2) happen-before (3); the volatile rule makes (3)\nhappen-before (4); transitivity chains them so (1) and (2) are visible at (4) —\neven though `a` and `b` are plain fields. **Rule of thumb:** one happens-before\nedge carries along everything that preceded it, which is exactly how `volatile`\nand locks publish data safely.\n",20,null,{"description":11},"Java volatile and memory model interview questions — the happens-before relationship, visibility vs atomicity, the volatile keyword, instruction reordering, and safe publication.","java\u002Fconcurrency\u002Fvolatile-memory-model","volatile & Memory Model","Concurrency","concurrency","2026-06-20","vmCnZOWFAcHaVb_RhIjOk8II7VciU1wMqi0NATdj5wI",[115,119,122,126,130],{"subtopic":116,"path":117,"order":118},"Threads & Synchronization","\u002Fjava\u002Fconcurrency\u002Fthreads",1,{"subtopic":120,"path":121,"order":12},"Synchronization & Locks","\u002Fjava\u002Fconcurrency\u002Fsynchronization-locks",{"subtopic":123,"path":124,"order":125},"Executors & Thread Pools","\u002Fjava\u002Fconcurrency\u002Fexecutors-thread-pools",3,{"subtopic":127,"path":128,"order":129},"Concurrent Collections","\u002Fjava\u002Fconcurrency\u002Fconcurrent-collections",4,{"subtopic":109,"path":21,"order":20},{"path":132,"title":133},"\u002Fblog\u002Fjava-volatile-memory-model","Java volatile & the Java Memory Model — Visibility, happens-before & Safe Publication",1782244117407]