Articles

Cache Coherence and the MESI Protocol, Explained

Cache coherence keeps each CPU core's private cache consistent with the others. The MESI protocol is the classic mechanism that makes it work.

Chisato Chisato · · 5 min read
Close-up of a silicon wafer

Cache coherence is the set of hardware rules that keep every CPU core’s private cache in agreement about the current value of shared memory, even though each core reads and writes through its own local copy. Without it, one core could update a variable in its cache while another core keeps computing with a stale copy of the same address — silently wrong results with no software bug to point to.

Why coherence is a problem at all

Modern CPUs give each core its own L1 and often L2 cache, private and fast, backed by a larger shared L3 cache and main memory. That’s essential for performance — a core waiting on main memory for every read would be idle most of the time — but it creates a correctness problem the moment two cores touch the same memory address. If core A writes to a variable that’s cached in both core A and core B, core B’s cached copy is now wrong unless something intervenes.

Software has no visibility into this. A thread reading a shared variable expects to see the most recent write, regardless of which core made it or where in the cache hierarchy the data currently lives. Cache coherence protocols are the hardware mechanism that preserves this illusion of one shared memory, invisibly, underneath a system with dozens of separate physical caches.

The MESI protocol

MESI is the classic coherence protocol, named for the four states a cache line can be in on any given core:

  • Modified (M) — this core has the only copy, and it’s been written; it differs from main memory. The core must write it back (or hand it off) before any other core can read that address.
  • Exclusive (E) — this core has the only copy, and it matches main memory. No write has happened yet, but the core is free to write without asking anyone else.
  • Shared (S) — this core has a copy, and so might other cores; all copies match main memory. Reads are fine; a write requires first notifying other cores to invalidate their copies.
  • Invalid (I) — this core’s copy is stale or absent and must be reloaded before use.

Every cache line on every core sits in one of these four states, tracked per line, and transitions between them are triggered by memory operations — both the local core’s own reads and writes, and coherence messages broadcast or snooped from other cores. A read of a line no one else has moves it to Exclusive; a read when another core already has it shared moves both to Shared; a write to a Shared line forces every other core’s copy to Invalid before the write proceeds, then moves the writer’s copy to Modified.

How cores agree: snooping and directories

Enforcing these transitions requires cores to know what other cores are doing to the same address, and there are two broad approaches.

Snooping has every core’s cache controller watch (snoop) a shared bus for memory transactions from other cores. If core B sees core A broadcast an intent to write to an address core B has cached, core B invalidates its own copy. This works well for a small number of cores sharing a bus but doesn’t scale — broadcasting to everyone gets expensive as core counts climb.

Directory-based coherence replaces broadcasting with a lookup. A directory tracks which cores hold a copy of each cache line and its state; a core wanting to write only needs to message the specific cores listed as sharers, not everyone. This scales far better and is standard in high-core-count server and datacenter chips, at the cost of directory storage overhead and slightly higher latency for the common case.

Why this matters for software

Cache coherence is why writing a value on one thread and reading it on another “just works” without the programmer manually flushing caches — the hardware guarantees every core eventually observes writes made by other cores to the same address. But coherence alone doesn’t guarantee ordering across different addresses; that’s the job of a CPU’s memory consistency model and, in software, of atomics and memory barriers. Coherence answers “will core B eventually see core A’s write to this address,” not “in what order will core B see writes to several different addresses.” Getting that distinction wrong is a common source of subtle concurrency bugs.

Coherence traffic is also a real performance cost, not just a correctness mechanism. False sharing is the classic symptom: two unrelated variables that happen to land in the same cache line get bounced between Modified and Invalid every time either core writes, even though the threads never touch each other’s actual data — the hardware doesn’t know the difference between two variables in one line and one variable two cores are fighting over. Padding hot variables to their own cache line is a standard fix. This interacts with out-of-order execution and branch prediction, since a core stalled waiting on a coherence transaction can’t retire instructions that depend on the stale or invalidated line, and it compounds with the effects of NUMA architectures, where coherence traffic between sockets is considerably more expensive than between cores on the same die.

StateCopy is only one?Matches memory?Write requires messaging others?
ModifiedYesNoAlready done
ExclusiveYesYesNo
SharedNoYesYes
InvalidMust reload first

Beyond MESI

Real processors extend MESI with additional states for specific optimizations. MESIF (used in some Intel designs) adds a Forward state so exactly one sharer is designated to respond to future read requests, avoiding redundant responses from every sharer. MOESI (used in some AMD designs) adds an Owned state that lets a modified line be shared directly from cache to cache without first writing back to memory. These are refinements on the same underlying idea: track state per line, and coordinate transitions so every core’s view of memory stays consistent, whether that coordination happens via snooping or a directory.

The takeaway

Cache coherence is the invisible hardware layer that lets many independent CPU caches behave like one shared memory. MESI’s four states — Modified, Exclusive, Shared, Invalid — describe what any core knows about a cache line at any moment, and transitions between them, driven by snooping or directory lookups, are what keep concurrent reads and writes correct across cores. It solves consistency of a single address across caches, not ordering across addresses, and its performance cost shows up most visibly as false sharing when unrelated data crowds into the same cache line.

Chisato Chisato · · 4 min read

What Is Moore's Law? Chip Scaling, Explained

Moore's Law is the observation that transistor density on a chip roughly doubles every couple of years. Why it drove decades of gains, and why it's slowing.

#Hardware #Chips #Computer Science
Chisato Chisato · · 4 min read

What Is a Northbridge and Southbridge? The Chipset

The northbridge and southbridge were the two chips that routed data between a CPU, memory, and peripherals before modern SoCs absorbed their jobs.

#Hardware #Computer Science