AutoResetEvent, ManualResetEvent против Монитора - PullRequest
14 голосов
/ 11 ноября 2009

Допустим, мне нужно организовать алгоритм синхронизации в .Net 3.5 SP1, и любой из примитивов синхронизации, перечисленных в заголовке, идеально подходит для этой задачи.

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

Я спрашиваю об этом, потому что я уже некоторое время кодирую, но без должного знания предмета.

Ответы [ 3 ]

19 голосов
/ 18 февраля 2010

WaitHandles выглядят очень похоже на Wait / Pulse Constructs, но разница в деталях: метод WaitHandles Set устанавливает Signal, даже если ни один поток не ожидает. Это означает, что если вы вызываете Set в потоке, а затем вызываете WaitOne в другом потоке с той же ручкой ожидания, второй поток будет продолжен. Ожидание и Pulse отличаются, Pulse сигнализирует только о потоке, который уже находится в очереди ожидания. Это означает, что если вы вызываете Pulse в потоке, а затем вызываете Wait в другом потоке для того же объекта, второй поток будет ждать вечно (тупик). Вы должны быть чрезвычайно осторожны, если используете Wait и Pulse, используйте его, только если вы знаете, что делаете, иначе вам может повезти ...

Чтобы создать поведение WaitHandle самостоятельно с помощью Monitor, Weather Reset или ManualReset, вам нужно сделать гораздо больше, чем просто Wait / Pulse Construct. Просто используйте инструменты, необходимые для выполнения работы :

Если вы не можете синхронизировать потоки с простой блокировкой или атомарными операциями, подумайте об использовании WaitHandles. Если вы не можете синхронизировать потоки с WaitHandles, подумайте об использовании Wait и Pulse.

4 голосов
/ 11 ноября 2009

Если можете, идите с монитором. Это похоже на CRITICAL_SECTION. AutoResetEvent / ManualResetEvent могут иметь немного больше накладных расходов, поскольку они могут совместно использоваться различными процессами, тогда как монитор принадлежит одному процессу.

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

Подождите, и пульс в порядке, если вы следуете некоторым простым правилам:

  1. Вы можете не беспокоиться о блокировке, если блокировка для вашего объекта не нужна, и вы можете заранее сказать, что она готова; если, однако, похоже, что вам придется подождать, вы должны получить блокировку, а затем убедиться, что вам все еще действительно нужно ждать, прежде чем вы действительно это сделаете; Вы также должны в большинстве случаев предполагать, что вы можете случайно проснуться независимо от того, готовы ли условия или нет, поэтому вы должны перепроверять условия каждый раз, когда вы просыпаетесь, и, если необходимо, повторно ждать.
  2. Импульс должен подаваться после установки условий, которые позволят продолжить код ожидания.
  3. Если у вас есть что-то вроде флага «выход», может быть полезно иметь каждый фрагмент кода, который получает блокировку, чтобы проверить флаг выхода после снятия блокировки и, если флаг установлен, повторно зафиксируйте замок и отправьте импульс. Затем вы могли бы установить подпрограмму выхода, чтобы установить флаг, попытаться получить блокировку с нулевым тайм-аутом и отправить импульс, только если блокировка может быть получена. Если регистрация не удалась, вы можете быть уверены, что какой-то другой фрагмент кода отправит необходимый импульс. Это позволит избежать любой вероятности того, что процедура 'quit' застрянет в замке.
...