What’s the difference between memory coherence and consistency?

Memory Coherence vs. Consistency

These are often confused terms in concurrent programming and multiprocessor systems, but they address different problems in shared memory architectures.

Memory Coherence deals with writes to the same memory location. A cache-coherent system ensures that any read of a data location returns the most recently written value. If CPU A writes to address X, then CPU B reads from address X, CPU B must see A’s write (unless something more recent overwrote it). Coherence prevents stale cached copies from being read.

Memory Consistency is about the ordering of all memory operations across different locations. It specifies when writes become visible globally and what ordering guarantees the system provides. A consistency model defines rules like: “Will a read-after-write to different addresses see the write?” or “How do operations from different processors appear to other processors?”

The Practical Difference

Think of coherence as a local guarantee (one address) and consistency as a global guarantee (all addresses).

Coherence example:

CPU 0: write X = 10
CPU 1: read X        // Must see 10 (assuming no later write)

Consistency example:

CPU 0: write X = 1
CPU 0: write Y = 2
CPU 1: read Y        // Does CPU 1 see the write to Y?
CPU 1: read X        // And what about X?

Coherence guarantees nothing about the order or visibility across different addresses. Consistency models define those guarantees. Without a consistency model, you can have coherence but still face visibility delays between different memory locations.

Common Consistency Models

  • Sequential Consistency (SC): Memory operations appear to execute in program order globally. Strongest guarantee, most restrictive.
  • Release Consistency: Synchronization operations (acquire/release) enforce ordering; non-synchronizing operations can reorder. Used in most modern systems.
  • Weak Consistency: Minimal guarantees; programmers must explicitly synchronize using barriers or atomic operations.

Modern multicore systems provide cache coherence at the hardware level (using MESI, MOESI, or similar protocols), but you must code for a consistency model. In languages like C++, Java, or Rust, the memory model defines what consistency guarantees you get.

Why This Matters

Weak synchronization and ordering can lead to subtle bugs:

// Thread 0
x = 1;
flag = 1;

// Thread 1
while (!flag);
printf("%d", x);  // Might print 0 even after checking flag!

Without explicit synchronization (atomic operations, locks, or acquire/release semantics), you’re relying only on coherence. You need consistency guarantees to ensure thread 1 sees both writes in order.

In practice, use proper synchronization primitives (mutexes, atomics, memory barriers) rather than relying on implicit ordering. Different consistency models make different guarantees, and modern systems use weak consistency requiring explicit synchronization.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *