Проблема переключения потоков и предотвращения взаимоблокировок - PullRequest
0 голосов
/ 27 октября 2010

, если в качестве производителя / потребителя есть два потока, лучше иметь следующую строку для предотвращения взаимных блокировок.Я знаю о живых блокировках, но предположим, что они выполняют большую работу перед вызовом этого метода Wait ():

// member variable
object _syncLock = new object();

void Wait()
{
   lock (_syncLock)
      {
         Monitor.Pulse(_syncLock);
         Monitor.Wait(_syncLock);
      }
}

Здесь невозможно, чтобы оба потока находились в состоянии ожидания.

Ответы [ 2 ]

2 голосов
/ 27 октября 2010

Это кажется слишком сложным.Просто правильно обработайте блокировку и избегайте этой проблемы.Если у вас есть только два потока, и они пытаются получить одинаковую, единственную блокировку (правильно), у вас не должно быть взаимоблокировок.Взаимная блокировка означает, что здесь происходит что-то еще.

При этом, если у вас есть возможность использовать TPL через .NET 4 (или расширения Rx в .NET 3.5), вы можете рассмотреть возможность использованияBlockingCollection<T> вместо.Он идеально подходит для использования в сценарии производитель / потребитель и работает без блокировки.

1 голос
/ 27 октября 2010

Если вы намереваетесь создать парный вариант шаблона производитель-потребитель, то последовательность будет Pulse до Wait для производителя и Wait до Pulse для потребителя.Вы можете сослаться на цифру 5 в статье Джо Даффи об этом .Howerver, имейте в виду, что, поскольку его реализация выполняет безусловный Wait в методе Enqueue, между производителем и потребителем возникнет эффект пинг-понга.В его реализации очередь может иметь только один элемент на одного производителя.Так что, если это ваше намерение, то это ваш билет.В противном случае вы можете адаптировать его как есть и применить некоторое условие 1 к Wait в методе Enqueue, чтобы заставить его вести себя как настоящий буфер FIFO.

Однако,как и Рид, я спрашиваю, почему BlockingCollection нельзя было использовать.Эта коллекция должна быть очень эффективной, так как она использует стратегию без блокировки для методов Add и Take.Конечно, как я упоминал выше, если вы действительно хотите парный вариант, то эта коллекция не будет соответствовать вашим требованиям, и вам придется свернуть свой собственный, используя в качестве отправной точки Джо Даффи.

1 Просто не забудьте использовать цикл while вместо проверки if перед применением ожидания.Monitor.Wait просто ожидает изменения состояния блокировки и ничего более, поэтому вам придется перепроверить условие ожидания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...