Skip to content
Olivier Coanet edited this page Sep 7, 2025 · 3 revisions

Each Disruptor has a single wait strategy (IWaitStrategy) that is responsible for notifying processors of new events. The wait strategy creates sequence waiters (ISequenceWaiter) which are used by event processors to wait for event sequences.

Built-in wait strategy types

Wait strategy Description Note
BlockingWaitStrategy Uses Monitor.Wait and Monitor.Pulse to notify of new events and then busy spins to wait for dependent sequences. This is the default wait strategy.
BlockingSpinWaitWaitStrategy Uses Monitor.Wait and Monitor.Pulse to notify of new events and then uses System.Threading.SpinWait to wait for dependent sequences. This strategy should not generate high CPU usage.
BusySpinWaitStrategy Busy spins to wait for new events and dependent sequences.
SleepingWaitStrategy Uses a mix of Thread.Yield and Thread.Sleep(0) to wait for new events and dependent sequences.
YieldingWaitStrategy Uses Thread.Yield to wait for new events and dependent sequences.
SpinWaitWaitStrategy Uses System.Threading.SpinWait to wait for new events and dependent sequences. This strategy should not generate high CPU usage.

Design notes

Please note that the wait strategy is both responsible for notifying about new events and for waiting until dependent sequences are available, i.e., that previous event handlers have processed the event. The API allows signalling of new events, but not signalling of sequence availability. Thus all wait strategies, even blocking ones, must rely on variations of spin waiting to wait for sequence availability. This spin waiting can generate high CPU usage, which is a common source of issues reported by users..

A few wait strategies use System.Threading.SpinWait. This synchronization type is implemented using a mix of Thread.SpinWait, Thread.Yield, Thread.Sleep(0) and Thread.Sleep(1). On Windows, the thread pause duration cannot be less than the system timer resolution, which is 15.6 ms by default. So a call to Thread.Sleep(1) can generate pauses of 15.6 ms. To avoid this issue, the Disruptor often uses its own synchronization type, AggressiveSpinWait, which does not call Thread.Sleep(1).

Changes

The wait strategy API evolved over time and it is now very different from the original Java version.
Here is the list of changes:

  • [V5] Use CancellationToken instead of ISequenceBarrier to notify shutdown.
    • Passing the sequencer barrier to wait strategies was slightly dangerous because the sequence barrier also exposed methods like Alert or ClearAlert.
    • CancellationToken is safer, more explicit, and more idiomatic for .NET.
  • [V5] Return a dedicated type SequenceWaitResult in WaitFor.
    • This type makes explicit that wait strategies can timeout.
    • This type avoids the previous exception-based design.
  • [V5] Use DependentSequenceGroup instead of the sequence couple Sequence cursor, ISequence dependentSequence.
    • This change makes the API more explicit, avoids exposing mutable sequences to wait strategies and slightly improves performance.
  • [V7] Extract ISequenceWaiter from IWaitStrategy
    • The wait strategy is now a factory of ISequenceWaiter.
    • The wait strategy can now more easily store dedicated state per waiter.
  • [V7] Use a dedicated type to identify sequencer waiter owners: SequenceWaiterOwner
    • The wait strategy can more easily identify the event handlers and apply custom logic per waiter.
Clone this wiki locally