следует ли синхронизировать доступ к методам Next/Publish разрушителя?

Я не привожу полный список, так как приведенного ниже кода достаточно для тех, кто знаком с Disruptor. Вопрос в том, является ли вызов методов Next и Publish потокобезопасным. Какой из приведенных ниже примеров будет правильным? Обратите внимание, что Attach можно вызывать из разных потоков одновременно. И у меня несколько потребителей.

Пример1. Заблокировать все:

    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);
        }
    }

Пример2. Заблокировать следующее:

    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);
    }

Пример3. Нет замка

    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);
    }

person Oleg Vazhnev    schedule 12.11.2012    source источник
comment
Даже если сами методы потокобезопасны, семантика примера 1 отличается от семантики 2 и 3. В первом примере вам гарантируется (если ваша синхронизация правильная), что содержимое ringBuffer не изменится, пока он заблокирован.   -  person millimoose    schedule 12.11.2012
comment
Беглый взгляд на код Disruptor говорит мне, что он, вероятно, потокобезопасен — кажется, что реализация этих методов (судя по именам частных методов) использует различные методы, используемые в неблокирующих параллельных коллекциях.   -  person millimoose    schedule 12.11.2012


Ответы (2)


Я автор разрушителя сети.

Разрушитель — это параллельная коллекция, поэтому после правильной настройки вам не нужно применять какую-либо блокировку. В вашем случае вы должны инициализировать RingBuffer с помощью MultiThreadedClaimStrategy, поскольку у вас есть несколько производителей и вы используете пример 3 для публикации в кольцевом буфере.

Тем не менее, я не одобряю использование Disruptor-Net в рабочем коде, я портировал его некоторое время назад в свободное время и не использовал в рабочем коде, это потребует дальнейшего тестирования.

Тем не менее, параллельная очередь .NET значительно быстрее, чем очереди Java, поэтому я бы предложил использовать ConcurrentQueue в качестве альтернативы disrutpor или BlockingCollection, который предлагает семантику, очень близкую к Disruptor.

person Olivier Deheurles    schedule 13.11.2012
comment
рад видеть вас здесь и спасибо за ответ! я тестировал BlockingCollection против Disruptor-net, и BlockingCollection намного медленнее в тестах, см. stackoverflow.com/questions/13334778/ Теперь я попытался заменить BlockingCollection на разрушитель в своем приложении, и почему-то он работает медленнее, чем BlockinCollection. Но я не использую MultiThreadedClaimStrategy, вместо этого я использую что-то вроде этого stackoverflow.com/a/13339465/93647, возможно, поэтому . Я планирую создать еще один отдельный тест для сравнения BlockingCollection и Disruptor. - person Oleg Vazhnev; 13.11.2012

Под капотом реализация Next() и Publish() основана на статическом классе Interlocked. Так что убедитесь, что код был разработан для потокобезопасности. Он выглядит безопасным для потоков и дрожит как единое целое. Но является ли он потокобезопасным? Я не знаю.

Этот проект не выглядит очень активным и сильно отстает от Java API. Некоторые тесты не проходят (в Mono), а некоторые функции вообще не тестируются (WorkerPool). Используйте с осторожностью.

Я отправил автору письмо с приглашением прокомментировать, подождем его разъяснений.

person avishayp    schedule 12.11.2012