false sharing
Two flatmates, Ann and Ben, never touch the same belongings — Ann only ever uses the left half of a shared drawer, Ben only the right half. They share nothing in reality. But there is one rule: whenever anyone opens the drawer, everyone else must close theirs and re-open it. Now every time Ann uses her stuff she forces Ben to slam and reopen his, and vice versa, all day. They fight constantly over a drawer despite never wanting the same thing. False sharing is this maddening situation in a cache: two cores keep invalidating each other's copy of a cache line even though they touch logically separate variables that just happen to live in the same line.
The mechanism comes straight from how coherence works. Caches keep coherence at the granularity of a whole cache line (typically 64 bytes), not per byte or per variable. If variable X (used only by core A) and variable Y (used only by core B) sit in the same 64-byte line, then when A writes X the coherence protocol invalidates the whole line in B's cache — even though B does not care about X. B's next access to Y then misses and refetches the line, and when B writes Y it invalidates A's copy in turn. The line ping-pongs between the two caches with constant misses and coherence traffic, although the program logic shares nothing.
False sharing is a vicious performance bug because the code looks perfectly parallel and is logically correct — the answer is right, just dramatically slower, sometimes many times slower than expected, and it leaves no trace in the source. It commonly bites arrays where each thread writes its own slot (slots packed within one line) or per-thread counters laid out next to each other. The cure is layout, not logic: pad or align the data so each thread's hot variable sits in its own cache line, so no two cores ever share a line. This is one reason cache-aware programmers think about lines, not just variables.
Eight threads each increment results[i] in an 8-element int array. All 8 ints fit in one 64-byte cache line, so every increment by any thread invalidates the line in the other seven caches — the line ping-pongs and the 'parallel' loop runs slower than one thread. Fix: pad each entry to its own 64-byte line, and the threads stop colliding.
Logically independent writes collide because they share a cache line; padding to separate lines removes the phantom contention.
False sharing never causes a wrong answer — only slowness — which is exactly why it is so easy to miss. It is a property of data layout in cache lines, not of the program's logic, and it is invisible in the source code.