Back to Advanced: Disruptor, Actor, False Sharing
Q4Question 4 of 5

What is the LMAX Disruptor?

Key Concepts
  • The Disruptor is a high-performance inter-thread messaging library built around a pre-allocated ring buffer.
  • Ring buffer: fixed-size array (power of two), slots hold reusable event objects, index via bitmask.
  • Sequences are monotonically increasing CAS counters that coordinate without locks.
  • Sequence barriers let consumers wait for data without spinning blindly or locking.
  • The single-writer principle eliminates write contention: one thread owns each sequence.
  • Sequences are padded to a full cache line to prevent false sharing.
  • Beats BlockingQueue because: no lock contention, no per-element allocation, no GC pauses.

Definition

The Disruptor is a lock-free, pre-allocated ring buffer coordinated by sequences and barriers under a single-writer rule, giving millions of events per second without BlockingQueue lock and allocation overhead.
  • Ring buffer – fixed-size array (power of two), pre-allocated, slots reused in place; index via bitmask (sequence & (size - 1)).
  • Sequences – monotonically increasing CAS counters; producers claim slots, consumers track progress.
  • Sequence barriers – consumers ask "how far can I safely read?" without spinning blindly or locking.
  • Single-writer principle – one thread owns each piece of data, eliminating write contention.
  • Cache-line padding – sequences padded to prevent false sharing between unrelated counters.
  • Advantage over BlockingQueue – no lock contention, no per-element allocation, no GC pauses.

Picture a circular conveyor belt at National Bank of India with a fixed number of trays. A trade order goes into the next empty tray (never creating a new tray). Processing stations downstream (risk, journaling, matching) follow the belt, each watching counters rather than fighting over a shared lock.

Understanding the Concepts

What is the ring buffer?

A fixed-size array whose length is a power of two. Slot access is a bitmask: sequence & (size - 1). Slots hold reusable event objects, so almost no garbage is created.

How do sequences coordinate without locks?

A producer claims the next sequence via CAS, writes the event in place, then publishes. Each consumer has its own sequence tracking how far it has processed.

What is a sequence barrier?

The barrier tracks dependent sequences. A consumer asks "how far can I safely read?" and the barrier returns the highest available sequence. Wait strategies trade CPU for latency: busy-spin for lowest latency, blocking for lower CPU.

What is the single-writer principle?

When only one thread writes to a given piece of data, write contention is zero. The Disruptor applies this by giving each participant its own sequence.

Why pad sequences to prevent false sharing?

Two unrelated counters on the same cache line invalidate each other across cores. Padding each sequence to a full cache line (64 bytes) prevents this.

How does it compare to BlockingQueue?

| Feature | BlockingQueue | Disruptor |
|---------|---------------|-----------|
| Coordination | Lock (put/take share one lock) | CAS on independent sequences |
| Allocation | Per-element (wrapper/node) | Pre-allocated, reused in place |
| GC pressure | High | Near zero |
| Cache behaviour | Lock state bounces between cores | Padded sequences, no false sharing |
| Throughput | Millions/sec with effort | 10M+ events/sec routinely |

How do you express consumer dependencies?

Dependencies form a graph. A matching consumer can wait behind a journaling consumer and a replication consumer, so the event is durably recorded before it is acted upon.

What are common interview follow-up questions?

  • How does the Disruptor handle backpressure?
  • What wait strategies are available and when do you use each?
  • How does the Disruptor compare to Chronicle Queue?

What are common mistakes?

A common mistake is not understanding the concept fully before using it in production banking applications.

Wrong approach:

JAVA
package com.bank.service;

public class TransferService {
    public void transfer(String fromAccount, String toAccount, double amount) {
        // WRONG: using double for money
        double balance = getBalance(fromAccount);
        balance = balance - amount;
    }
    private double getBalance(String id) { return 10000.0; }
}

Correct approach:

JAVA
package com.bank.service;

import java.math.BigDecimal;

public class TransferService {
    public void transfer(String fromAccount, String toAccount, BigDecimal amount) {
        // CORRECT: using BigDecimal for money
        BigDecimal balance = getBalance(fromAccount);
        balance = balance.subtract(amount);
    }
    private BigDecimal getBalance(String id) { return new BigDecimal("10000.00"); }
}

Always use BigDecimal for monetary calculations in banking systems to avoid floating-point precision errors.

Visual Overview

DIAGRAM
  Disruptor Ring Buffer:

  ┌───┬───┬───┬───┬───┬───┬───┬───┐
  │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │  size = 8 (power of 2)
  └───┴───┴───┴───┴───┴───┴───┴───┘
    ▲                           ▲
    │ Consumer seq = 2          │ Producer seq = 5
    │ (processed up to 2)       │ (published up to 5)

  slot index = sequence & (size - 1)
  sequence 5 → slot 5 & 7 = 5

  Consumer Dependency Graph:
  Producer → [Risk Check] → [Matching Engine]
          → [Journaling] ↗
          → [Replication]↗
  Matching waits for journaling AND replication

  Single Writer: each sequence owned by one thread
  Padding: each sequence padded to 64-byte cache line

Key Takeaway

The LMAX Disruptor is a lock-free ring buffer coordinated by sequences and barriers under a single-writer rule. Pre-allocated, reused slots create near-zero garbage. CAS-based sequences eliminate lock contention. Cache-line padding prevents false sharing.

It beats BlockingQueue because there is no shared lock, no per-element allocation, and no GC pauses.

At National Bank of India our trading platform uses the Disruptor's ring buffer between feed ingestion, risk validation, journaling, and matching, achieving millions of events per second with microsecond latency.

Remember one sentence: the Disruptor is a lock-free, pre-allocated ring buffer coordinated by sequences and barriers under a single-writer rule, which is how it reaches millions of events per second without BlockingQueue overhead.

---

Share
Use ← → arrow keys to navigate