The MFENCE vs. LFENCE vs. SFENCE Asymmetry: Why x86 Has Three Fences and You Probably Need Only One

2026-07-24

x86 gives you three memory fence instructions, and their names suggest a clean symmetry: SFENCE for stores, LFENCE for loads, MFENCE for both. That mental model is wrong, and the wrongness is expensive.

Under x86-TSO, normal WB (write-back) memory already guarantees load-load, store-store, and load-store ordering. The only reordering the hardware allows is a later load passing an earlier store to a different address — the store buffer sits in front of loads, and loads read from cache while the store is still parked. Every fence exists to deal with this one hole, or with the weird memory types that sit outside TSO.

Concrete example — Dekker-style handshake:

Thread A: store x=1; load y;
Thread B: store y=1; load x;

Without a fence, both threads can see 0 because each load reads cache while its own store sits in the buffer. SFENCE won't fix it — it doesn't order stores against loads. LFENCE won't fix it — it doesn't drain the store buffer. You need MFENCE, or equivalently a LOCK-prefixed instruction (which also drains).

Rule of thumb for cost on Skylake-class cores:

The asymmetry exists because x86 already gives you three-quarters of what "memory barrier" means for free. The fences only pay for the corners TSO refuses to close.

Key Takeaway: On x86, MFENCE is the only fence that drains the store buffer — SFENCE and LFENCE handle weakly-ordered stores and speculation respectively, and a locked XCHG is usually the fastest way to get full sequential consistency.

All newsletters