The Java Language Specification has a section titled "Word Tearing" (§17.6) whose guarantee is different from its rule that `long` and `double` may be treated non-atomically. State the §17.6 guarantee and explain what it forces a JVM implementation to do on hardware that cannot store a single byte directly.
answer
- §17.6 = neighbours must not interfere; §17.7 = one value split in half
- Byte store via word read-modify-write would lose a neighbour's write
- Implementation must use narrow stores or atomic RMW (LL/SC, CAS)
- Different threads may write different array elements safely
- False sharing = performance; word tearing = correctness, and forbidden
basics
~20 s§17.6 forbids word tearing: updating one field or one array element must never disturb any other field or element. On hardware without byte-granularity stores, an implementation may not implement a byte[] element write as read-modify-write of the enclosing word — it must use an atomic operation instead.
solid answer
~60 sTwo differently-named hazards get conflated. §17.7 is about a *single* `long` or `double` access being split in half. §17.6, "Word Tearing", is about *neighbours*: the specification requires that updating one field or one array element must have no effect on any other field or array element, and in particular that reading one must never see a value written only to a different one. The rule has teeth on hardware whose smallest store is a 32-bit word. A naive implementation of `bytes[3] = x` there would read the enclosing word, splice in the byte, and write the word back. If another thread concurrently wrote `bytes[2]`, one of the two updates would be silently lost — even though the threads touched disjoint elements. The specification forbids that, so an implementation on such hardware must use an atomic read-modify-write (load-linked/store-conditional or compare-and-set) or genuine byte stores. The practical consequence: distinct threads may write distinct elements of a `byte[]` or `boolean[]` without locks and without corrupting each other. It also explains why `boolean[]` is not bit-packed. This is a *correctness* guarantee — false sharing is the unrelated *performance* effect on the same layout.
code
java · 7 linesbyte[] data = new byte[1024];
// Thread A // Thread B
data[0] = 1; data[1] = 2;
// §17.6 guarantees neither write can clobber the other,
// however the JVM packs the array in memory.
// (Publishing the results to a reader still needs synchronisation.)go deeper
Know the outcome: writing different array elements from different threads cannot corrupt each other, and that this is a language guarantee.
State §17.6 as a rule about neighbours and distinguish it from the long/double non-atomicity rule about a single value.
Explain the implementation the rule forbids (word-granularity read-modify-write for narrow stores), the required alternative, and the clean separation from false sharing as a performance effect.
Use it as an example of the memory model pushing hardware-portability burdens onto the implementation rather than the programmer, and reason about where that boundary should sit for off-heap and foreign-memory access where the guarantee does not apply automatically.
## Two rules, similar names, different hazards Candidates routinely merge two adjacent sections of the Java Language Specification. Keeping them apart is exactly what this question tests. - **§17.7, Non-Atomic Treatment of `double` and `long`.** One access to one 64-bit field may be split into two 32-bit halves, so a reader can see a mix of two writes to *the same variable*. - **§17.6, Word Tearing.** Updating one variable must not disturb a *different* variable that happens to live nearby in memory. Reading one field or array element must never see a value written only to another field or element. The first is about a value being cut in half. The second is about neighbours interfering. The second is a guarantee the platform gives you unconditionally; the first is a guarantee it withholds unless you say `volatile`. ## Why §17.6 needs saying at all On a machine whose smallest addressable store is one 32-bit word, there is a tempting implementation of a `byte` array: pack four elements per word, and implement an element write as *read the word, replace the relevant 8 bits, write the word back*. That is a read-modify-write of the whole word. Now let two threads write disjoint elements that share a word: ``` Thread A: writes bytes[0] = 1 Thread B: writes bytes[1] = 2 read word -> [0,0,0,0] read word -> [0,0,0,0] splice -> [1,0,0,0] splice -> [0,2,0,0] write word -> [1,0,0,0] write word -> [0,2,0,0] // A's write vanished ``` The threads shared no variable. Neither did anything wrong — no synchronisation is required to write to *different* variables. Yet an update disappeared. That is word tearing, and §17.6 outlaws it: the implementation, not the programmer, must prevent it. On such hardware, an implementation must either use whatever narrow store the machine does have, or perform the word update with an atomic read-modify-write (load-linked/store-conditional, or a compare-and-set retry loop) so a concurrent neighbour update cannot be lost. Modern mainstream CPUs have byte stores, so the requirement is free there — but the guarantee is what makes the language's memory model well-defined regardless. ## What programmers get from it The guarantee is more useful than it looks: - **Different threads may write different elements of any array without coordination.** Partitioning a `byte[]`, `boolean[]`, `short[]` or `char[]` by index and letting each thread own a slice is safe from corruption. Each thread still needs synchronisation to *publish* its results to a reader, but no element write can damage a neighbour. - **Adjacent fields are independent.** Two threads writing two different fields of the same object need no mutual exclusion for the sake of the fields' storage, however tightly the JVM packs them. - **`boolean[]` is a byte per element, not a bit per element.** A bit-packed representation would make per-element writes read-modify-write of a shared word — precisely what §17.6 forbids without atomic operations, which would make every element write expensive. Paying a byte per boolean is the cheaper way to honour the rule. (Note that a `boolean` *field* inside an object may still be packed with other fields; the guarantee is about non-interference, not about layout.) ## The thing it is *not*: false sharing The usual follow-up. **False sharing** is when two threads write distinct variables that share a *cache line*: no update is lost, results are correct, but the cache line ping-pongs between cores and throughput collapses. That is a performance phenomenon, addressed with padding or contended-layout hints. Word tearing would be a *correctness* failure — an update actually disappearing — and the specification simply forbids it. Same physical picture (variables sharing storage), completely different consequence, completely different remedy. Being able to distinguish them cleanly is the mark of a candidate who has read the memory model rather than absorbed folklore. ## Bringing it together A good answer states §17.6 in one sentence ("updating one field or array element must not affect any other"), gives the concrete failing implementation it rules out (word-granularity read-modify-write for a byte store), names the required alternative (narrow stores or atomic RMW), draws out the programmer-visible consequence (independent element writes are safe; `boolean[]` is byte-per-element), and finally separates it from both §17.7 tearing of a single 64-bit value and from false sharing as a performance effect.
- How is word tearing different from false sharing?Word tearing would be a correctness failure: a write to one variable destroys a concurrent write to a different variable, so an update is silently lost. The specification forbids it outright, so it cannot happen in Java. False sharing is purely a performance effect — two threads writing distinct variables in the same cache line cause that line to bounce between cores, with fully correct results but poor throughput, mitigated by padding or layout changes.
- Does §17.6 mean that concurrent writes and reads of distinct array elements need no synchronisation at all?It means no write can corrupt a different element, so the storage is safe. It does not give visibility or ordering: a reader of an element written by another thread still needs a happens-before relationship to be guaranteed to observe it. The usual pattern is that each worker owns a slice, and a synchronisation action at the end — joining the threads, or a latch — publishes all the results.
- Why is a `boolean[]` typically one byte per element rather than one bit?Because bit packing would make each element write a read-modify-write of a shared byte or word, and §17.6 forbids that from disturbing neighbouring elements. Honouring the rule would then require an atomic read-modify-write on every element write, which is far more expensive than the memory saved. Spending a byte per element makes each write an independent narrow store.
Think of a shared whiteboard divided into cells. Word tearing would be a marker so wide that writing in your cell erases part of your neighbour's — the language forbids selling that marker. False sharing is everyone reaching over the same section of board and getting in each other's way: nothing is erased, but nobody moves quickly.
saying these in an interview costs you the question
- Treating §17.6 word tearing and the long/double non-atomicity rule as the same thing
- Claiming Java programs can suffer word tearing and that you must pad arrays to avoid it
- Saying false sharing can lose updates
- Believing that because element writes cannot interfere, no synchronisation is needed to read another thread's results
- Assuming `boolean[]` is bit-packed to save memory