should I synchronize access to disruptor Next/Publish methods?
Asked Answered
E

2

2

I'm not providing full listing as below code is enough for those who familar with disruptor. The question is if calling Next and Publish methods is thread-safe. Between examples below what would be the correct one? Note that Attach can be called from different threads at the same time. And I have multiple consumers.

Example1. Lock everything:

    private object attachLock = new object();

    // can be called from parallel threads
    public void Attach(OrdersExecutor oe)
    {
        lock (attachLock)
        {
            long sequenceNo = ringBuffer.Next();
            ringBuffer[sequenceNo].Value = oe;
            ringBuffer.Publish(sequenceNo);
        }
    }

Example2. Lock Next:

    private object attachLock = new object();

    // can be called from parallel threads
    public void Attach(OrdersExecutor oe)
    {
        long sequenceNo;
        lock (attachLock)
        {
            sequenceNo = ringBuffer.Next();
        }
        ringBuffer[sequenceNo].Value = oe;
        ringBuffer.Publish(sequenceNo);
    }

Example3. No lock

    private object attachLock = new object();

    // can be called from parallel threads
    public void Attach(OrdersExecutor oe)
    {
        long sequenceNo = ringBuffer.Next();
        ringBuffer[sequenceNo].Value = oe;
        ringBuffer.Publish(sequenceNo);
    }
Engender answered 12/11, 2012 at 19:39 Comment(2)
Even if the methods themselves are threadsafe, the semantics of example 1 are different from 2 and 3. In example one, you're guaranteed (if your synchronisation is correct) that the contents of ringBuffer don't change while it's locked.Presentative
A brief glance at the Disruptor code tells me that it's probably thread-safe - the implementation of those methods seems (going by private method names) to use various techniques used in nonlocking concurrent collections.Presentative
M
5

I'm the author of disruptor-net.

The disruptor is a concurrent collection, so you don't have to apply any locking once configured properly. In your case you should initialize the RingBuffer with a MultiThreadedClaimStrategy since you have multiple producers and use Example 3 to publish to the ring buffer.

That said, I discourage usage of disruptor-net in production code, I ported it a while ago on my spare time and have not used it in production code, it would require further testing.

That said, .NET concurrent queue is significantly faster than Java queues so I would suggest to use ConcurrentQueue as an alternative to the disrutpor, or BlockingCollection which offers a semantic very close to the Disruptor.

Medication answered 13/11, 2012 at 6:28 Comment(1)
glad to see you here and thank for response! i've tested BlockingCollection vs Disruptor-net and BlockingCollection is much slower in tests, refer to #13335278 Now i've tried to substitute BlockingCollection with disruptor in my application and somehow it works slower than BlockinCollection. But I do not use MultiThreadedClaimStrategy, instead i do use something like that https://mcmap.net/q/1561677/-disruptor-example-with-1-publisher-and-4-parallel-consumers probably that's why. I plan to create one another standalone test to compare BlockingCollection and disruptor.Engender
L
1

Under the hood, the implementation of Next() and Publish() is based on the Interlocked static class. So sure the code was designed to be thread safe. It looks thread safe, and quakes as one. But is it thread safe? I don't know.

This project doesn't seem very active, and lags way behind the Java API. Some tests fail (on Mono), and some features are not tested at all (WorkerPool). Use with care.

I've mailed the author inviting him to comment, let's wait for his clarifications.

Lagting answered 12/11, 2012 at 21:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.