Fundamentals 38 min read

Why Your Multithreaded Code Might Misbehave: A Deep Dive into Language Memory Models

This article explains how programming‑language memory models define the guarantees for shared‑memory concurrency, illustrates common pitfalls such as ordinary‑variable problems and instruction‑reordering, and surveys the evolution of memory models in Java, C++, Rust, Swift, JavaScript and hardware architectures.

Cognitive Technology Team
Cognitive Technology Team
Cognitive Technology Team
Why Your Multithreaded Code Might Misbehave: A Deep Dive into Language Memory Models

Programming‑language memory models answer the question of what behavior parallel programs can rely on when they share memory. A simple example with two variables x and done shows how a thread may try to send a message by writing x and signalling with done. Without proper synchronization the program may never terminate or may print the wrong value.

Common Issues with Ordinary Variables

Ordinary‑variable problem : Compilers often cache a variable in a register. If thread 2 copies done to a register before thread 1 writes it, the loop may never observe the update.

Instruction‑reordering problem : Compilers may reorder writes to x and done or reads of x and done, causing the program to print x as 0 even after thread 1 has stored 1.

Fixing the Problems with Atomic Variables

Making done an atomic variable (or using atomic operations) forces the compiler to emit code that respects the required ordering:

Thread 1 must ensure the write to x is visible before the write to done.

Thread 2 must reload done on each loop iteration.

Thread 2 must read done before reading x.

The generated code must disable hardware optimisations that could re‑introduce these issues.

With done atomic, the program reliably terminates and prints 1, eliminating the data race between the two threads. Modern languages adopt the Data‑Race‑Free Sequential Consistency (DRF‑SC) guarantee: a program without data races behaves as if executed on a sequentially consistent machine.

Historical Perspective: Java Memory Models

Original Java Memory Model (1996)

Java was the first mainstream language to attempt a formal memory model. It introduced mutexes and "volatile" variables, which required reads and writes to appear in program order in main memory. However, the 1996 specification had two serious flaws: volatile variables were not truly synchronising, and the model forced overly strong coherence that prevented useful compiler optimisations.

New Java Memory Model (2004)

In response, the JSR‑133 effort produced a model adopted in Java 5.0 that uses DRF‑SC. Synchronisation actions include thread creation, lock/unlock, and volatile reads/writes. The model defines a global total order of synchronisation actions, which determines the "happens‑before" relation used to reason about data‑race‑free programs.

C++11 Memory Model (2011)

C++ adopted a similar model but does not guarantee any behaviour for programs that contain data races; such programs have undefined behaviour. C++11 introduced three classes of atomic operations: sequentially consistent, acquire/release (weak), and relaxed (no synchronisation). The presence of relaxed atomics re‑introduces many of the complexities found in Java.

Acquire/Release Atomics and Their Pitfalls

Acquire/release atomics provide only coherence, not full sequential consistency. This can lead to surprising behaviours, for example a condition‑variable implementation that may deadlock because the acquire/release ordering does not enforce the necessary ordering between the notification and the wait.

Relaxed Atomics

Relaxed atomics have no synchronisation effect and are indistinguishable from ordinary reads/writes, except that data races on relaxed atomics are not considered data races. This makes reasoning about programs that mix relaxed atomics with ordinary accesses extremely difficult.

Other Languages

C11 adopted the C++11 model, and both Rust 1.0 (2015) and Swift 5.3 (2020) fully adopt the C/C++ memory model, including DRF‑SC and all atomic types.

Hardware Support for Efficient Sequentially Consistent Atomics

Modern architectures such as ARMv8 provide dedicated load‑acquire ( ldar) and store‑release ( stlr) instructions that implement sequentially consistent atomics efficiently. Similar support exists in RISC‑V, reducing the performance gap between strong and weak atomics.

JavaScript Memory Model (ES2017)

Although JavaScript was traditionally single‑threaded, the introduction of SharedArrayBuffer and Web Workers required a memory model. ES2017 defines only sequentially consistent atomics and a detailed semantics for data‑race programs, which initially conflicted with ARMv8's behaviour. Subsequent revisions fixed these issues.

Conclusion

Across C, C++, Java, JavaScript, Rust and Swift, the common observations are:

All provide sequentially consistent synchronising atomics for coordinating non‑atomic code.

All aim to give data‑race‑free programs the illusion of sequential execution.

All expose a way to perform intentional data races (relaxed atomics in C/C++/Rust/Swift, ordinary accesses in Java/JavaScript).

No language has completely eliminated paradoxical behaviours such as "out‑of‑thin‑air" values, though informal reasoning and recent revisions have mitigated many cases.

Hardware vendors now support efficient implementations of the required atomic primitives.

Formal verification efforts continue to improve our understanding of these models, and recent work has produced mechanised proofs of compiler correctness for JavaScript on ARM, POWER, RISC‑V and x86‑TSO.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaJavaScriptconcurrencyRustCmultithreadingMemory Modelatomic operations
Cognitive Technology Team
Written by

Cognitive Technology Team

Cognitive Technology Team regularly delivers the latest IT news, original content, programming tutorials and experience sharing, with daily perks awaiting you.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.