Самый быстрый способ передачи данных между потоками

Я не спрашиваю о самом идиоматичном способе использования фоновых рабочих процессов, пула потоков или TPL.

Я пытаюсь выяснить, какие подходы являются самыми быстрыми, когда речь идет о передаче данных из одного потока в другой с использованием .NET.

В настоящее время я играю с кольцевым буфером с индексом записи и индексом чтения. Таким образом, у меня вообще нет синхронизации потоков, кроме атомарных операций по обновлению индекса чтения/записи. (Я не уверен на 100%, но чтение и ++ для целых чисел являются атомарными в .NET, верно? Или целое число может быть перезаписано наполовину, когда его читает один поток?)

                         Write Index
                              V
index 0 [_][_][_][_][_][_][_][_][_][_][_] --> higher index
               ^
           Read Index

Является ли это разумным подходом, когда дело доходит до взаимодействия между потоками?

Я не использую его для какого-либо реального проекта, я просто хочу лучше понять, что здесь работает, а что нет.

[edit] Хорошо, я готов к публичному позору:

https://gist.github.com/rogeralsing/8121376

Сколько дыр в этом коде?


person Roger Johansson    schedule 24.12.2013    source источник
comment
Это похоже на регулярное выражение, теперь у вас есть две проблемы. Вы не можете достоверно сказать, когда буфер заполнен, вы не можете заблокировать производителя, вы не можете заблокировать потребителя, когда буфер пуст. Есть идиоматический способ, но вы не хотите о нем слышать.   -  person Hans Passant    schedule 24.12.2013
comment
@RogerAlsing Стандартные целочисленные операции НЕ являются атомарными.   -  person egur    schedule 24.12.2013
comment
@HansPassant Я знаю, что для этого есть идиоматические способы, я использую TPL для самых разных вещей, я просто пытаюсь понять, что возможно, а что нет для конкретных случаев использования. и, как уже говорилось, я не использую это ни для чего, просто учусь.   -  person Roger Johansson    schedule 24.12.2013
comment
++ не является атомарным. Вы можете использовать Interlocked.Increment, хотя...   -  person i3arnon    schedule 25.12.2013
comment
Если у вас есть код, который, по вашему мнению, работает, и вы хотите, чтобы он был проверен, вы можете рассмотреть codereview.stackexchange.com.   -  person svick    schedule 25.12.2013


Ответы (1)


Я думаю, это зависит от того, как вы определяете «самый быстрый» и «между потоками». Я думаю, что ConcurrentBag<T> действительно хороший способ. Если я правильно помню, реализация использует какой-то связанный список, чтобы уменьшить объем большинства блокировок, чтобы он стал более масштабируемым. Это быстро между двумя простыми потоками? вам нужно проверить, но он использует ваши ядра, поэтому ваше приложение в целом будет работать быстро.

person i3arnon    schedule 24.12.2013
comment
AFAIK, ConcurrentBag оптимизирован для случая, когда один и тот же поток является как производителем, так и потребителем. Я думаю, что для отправки из одного потока в другой ConcurrentQueue будет быстрее. - person svick; 25.12.2013