Синхронизация очереди и операции в C # - PullRequest
2 голосов
/ 19 июля 2011

Если очередь синхронизирована:

var _item = Queue.Synchronized(new Queue());

Могу ли я вызвать для нее методы, такие как постановка и удаление из нее, без использования операторов блокировки?

Мой текущий код:

lock (_item.SyncRoot)
{
    _item.Enqueue(obj);
}

Можно ли использовать потокобезопасное использование:

_item.Enqueue(obj);
var item = _item.Dequeue();

Ответы [ 3 ]

4 голосов
/ 19 июля 2011

Это в значительной степени то, что делает SynchronizedQueue, но есть проблема ... обычно вам нужно проверить .Count и .Dequeue() в одной атомной единице - не проверять .Count (одна единица), затем .Dequeue() (другая единица) - вы не можете доверять .Count вообще после того, как блокировка снята, и .Dequeue() скинет, если другая Нить украла работу.

Возможно, попробуйте ConcurrentQueue<T> в 4.0 (с .TryDequeue()) или используйте Queue<T> и lock.

4 голосов
/ 19 июля 2011

Вызов Enqueue и вызов Dequeue являются потокобезопасными.
Тем не менее, ваш пример кода не является:
Между вызовом Enqueue и вызовом Dequeue мог быть переключатель потока. Это означает, что item может быть другим экземпляром, чем obj, или вызов Dequeue вызывает исключение, потому что теперь он пуст.

Чтобы сделать ваш пример кода безопасным, вам все равно необходимо явно заблокировать:

lock(_item.SyncRoot)
{
    _item.Enqueue(obj);
    var item = _item.Dequeue);
}

Только теперь гарантируется, что item reference-равно obj при любых обстоятельствах.

2 голосов
/ 19 июля 2011

С MSDN

Для гарантии безопасности резьбы Очередь, все операции должны быть выполнены только через эту обертку.

Перечисление через коллекцию по сути не потокобезопасный процедура. Даже когда коллекция синхронизированы, другие потоки все еще могут изменить коллекцию, которая вызывает перечислитель для исключения. Чтобы гарантировать безопасность нити во время перечисление, вы можете заблокировать Коллекция в течение всего Перечисление или ловить исключения в результате изменений, сделанных другими резьб.

Так же, как и в ответе Джона Скита здесь , вы могли бы быть лучше или использовать блокировку, поскольку перечисление может вызвать исключение.

Грегс ответ также говорит о том, что Марк упоминает, что Count не безопасен для потоков.

...