Menu

Earn Premium with Referrals

Invite your friends and earn Premium rewards through our referral program.

See how it works and start inviting friends.

False Sharing & Memory Barriers
OS

False Sharing & Memory Barriers

Understand cache coherence, false sharing performance pitfalls, and memory ordering.

Modern CPUs have multiple cores, each with its own L1/L2 cache. Cache coherence protocols (like MESI) ensure that when one core writes to a cache line, other cores’ copies are invalidated. This creates subtle performance traps.

Cache Lines

Memory is transferred between RAM and CPU caches in fixed-size blocks called cache lines (typically 64 bytes on x86). If a program accesses a single byte, the entire 64-byte block is loaded into the cache.

False Sharing

Two threads access different variables that happen to sit on the same cache line. Neither thread uses the other’s variable, but the cache coherence protocol treats them as the same line.

Thread A writes to x (on cache line N)
→ Core B's copy of line N is invalidated
Thread B writes to y (on the same line N)
→ Core A's copy of line N is invalidated
→ Both cores keep reloading the same line

Result: performance collapses — up to 100x slower. Neither thread shares data (no real sharing), but the hardware treats it as sharing. Hence “false sharing.”

Fix: Padding

// Before: x and y share a cache line
struct { int x; int y; };

// After: padded to separate cache lines
struct { int x; char pad[64]; int y; };

Memory Barriers (Fences)

CPUs reorder memory operations for performance. A memory barrier prevents reordering around the barrier.

// Thread 1                    Thread 2
data = 42;                     while (!flag_ready);
flag_ready = 1;                print(data);

Without a barrier: Thread 2 could see flag_ready == 1 but data == 0 — the write to data might be delayed past the write to flag_ready.

Barrier Types

BarrierPrevents
mfence (full)All reordering around the fence
acquire (load)Later loads/stores moving before
release (store)Earlier loads/stores moving after

In high-level code: use std::atomic or synchronized — compilers insert the right barriers.

Q: What is false sharing?

A: Two threads access different variables that sit on the same cache line. Although they don’t share data logically, the cache coherence protocol treats the line as shared — invalidating it across cores on every write. This causes massive cache contention with zero data sharing.

Q: How do you detect false sharing?

A: Perf counters showing high cache miss rates with low actual data sharing. Thread A writes to address X, thread B writes to address Y, but X and Y are within 64 bytes. Tools: Linux perf (cache-misses), Intel VTune, Valgrind.

Q: How do you fix false sharing?

A: Pad structures so that fields accessed by different threads land on different cache lines. alignas(64) or __attribute__((aligned(64))) on C++ structs. In Go/Java, the compiler may add padding automatically.

Q: What is a memory barrier and when is it needed?

A: A CPU instruction that prevents memory reordering across the barrier. Needed when implementing lock-free code or custom synchronization. Regular mutexes already include the necessary barriers. Without them, you can observe operations happening in a different order than written in source code.

My Private Notes

Notes are auto-saved locally to this device.