Advanced 28 min readModule: Module 15: Lock-Free Concurrency: Interlocked & LMAX Disruptor
Lock-Free C#: Interlocked & LMAX Disruptor Architecture
Eliminate lock contention in .NET: `System.Threading.Interlocked` CAS operations, hardware CPU memory fences with `Volatile`, cache padding with `[StructLayout(LayoutKind.Explicit)]`, and implementing an ultra-low-latency LMAX Disruptor ring buffer.
What You Will Learn in This Lesson
- Why `lock (obj)` (Monitor) causes thread context switching and convoying under high contention
- Atomic CPU operations with `Interlocked.CompareExchange` and `Interlocked.Add`
- Eliminating False Sharing in C# structs using `[StructLayout(LayoutKind.Explicit)]` and `[FieldOffset(64)]`
- The LMAX Disruptor pattern: pre-allocated ring buffers with sequential sequence barriers
Introduction & Core Concept
Traditional multithreading in C# relies on the `lock` keyword (Monitor enter/exit). Under high load with dozens of threads, lock contention causes the OS kernel to put threads to sleep, incurring expensive context switches (1,000ns+). Lock-free programming uses CPU atomic instructions (`Interlocked`) to synchronize state in under 5 nanoseconds with zero thread parking.
WHY DOES THIS MATTER IN THE REAL WORLD?
High-Frequency Trading matching engines and low-latency message buses process millions of transactions per second per CPU core using lock-free ring buffers.
Syntax & Structure
csharp
Interlocked.CompareExchange(ref location, newValue, comparand);Volatile.Write(ref flag, 1);Lock-Free Atomic Sequence Counter with Cache Line Padding in C#
csharpcsharp
1234567891011121314151617181920212223242526272829303132333435363738394041424344// Lock-Free Atomic Ring Buffer Sequence with 64-Byte Cache Paddingusing System;using System.Runtime.InteropServices;using System.Threading;using System.Threading.Tasks;// Cache line padding eliminates False Sharing between Producer and Consumer![StructLayout(LayoutKind.Explicit, Size = 128)]public struct PaddedAtomicSequence{[FieldOffset(64)] // Placed on its own dedicated 64-byte cache linepublic long Value;public long Increment(){return Interlocked.Increment(ref Value);}public long ReadVolatile(){return Volatile.Read(ref Value);}}public class LockFreeDisruptorDemo{public static void Main(){Console.WriteLine("=== Lock-Free C#: Interlocked & Cache Line Padding ===");var producerSequence = new PaddedAtomicSequence();// Spawn concurrent tasks updating sequence atomically without locksParallel.For(0, 100_000, i =>{// Interlocked atomic instruction (LOCK XADD in x86-64 assembly)producerSequence.Increment();});long finalValue = producerSequence.ReadVolatile();Console.WriteLine($"Final Atomic Sequence Value: {finalValue}");Console.WriteLine("✅ 100,000 concurrent atomic increments completed with ZERO mutex locks!");}}
Line-by-Line Technical Breakdown
1The LMAX Disruptor Architecture: A circular array (ring buffer) where items are pre-allocated at startup. Producers and Consumers claim sequence numbers atomically via `Interlocked`. Because memory is never allocated or freed dynamically, Garbage Collection is 0% and throughput exceeds 10,000,000 events/sec.
Try It Yourself (Interactive Editor)
Modify the code in real-time and click Run to test live browser output and console logs.
Intelligent Code Runner & Live Sandbox[CSHARP]
CSHARP SOURCE EDITOR
Interactive Live CodeCommon Mistakes & How to Avoid Them
#1: Using `volatile` keyword on fields and assuming operations like `counter++` are atomic.
The `volatile` keyword only controls memory barrier reads/writes; it does NOT make compound operations (`++`, `+=`) atomic. `Interlocked` is required.
Incorrect / Antipattern
private volatile int counter; public void Inc() { counter++; } // RACE CONDITION!Correct / Professional Solution
private int counter; public void Inc() { Interlocked.Increment(ref counter); }Industry Best Practices & Professional Standards
- Use `Interlocked` for atomic counters and flags.
- Use `[StructLayout(LayoutKind.Explicit)]` to pad atomic sequence numbers across 64-byte boundaries.
- Use `System.Threading.Channels` as a high-performance built-in alternative to raw Disruptor ring buffers.
Lesson Summary & Core Takeaways
- `Interlocked` operations provide sub-5ns atomic synchronization without OS locks.
- Cache line padding eliminates False Sharing between CPU cores.
- The LMAX Disruptor pattern achieves ultra-high event throughput via lockless ring buffers.