Объяснение текста о потоковой обработке в “C # 3.0 в двух словах”

StackOverflow https://stackoverflow.com/questions/2322694

Вопрос

Во время чтения C # 3.0 в двух словах Автор: Джозеф и Бен Альбахари, я наткнулся на следующий абзац (страница 673, первый абзац в разделе под названием "Сигнализация с помощью ожидания и импульса")

"Тот самый Монитор класс предоставляет другую конструкцию сигнализации с помощью двух статических методов, Подожди и Пульс.Принцип заключается в том, что вы сами пишете логику сигнализации, используя пользовательские флаги и поля (заключенные в замок заявления), а затем ввести Подожди и Пульс команды для уменьшения вращения процессора.Преимущество этого низкоуровневого подхода заключается в том, что с помощью всего лишь Подожди, Пульс, и тот замок таким образом, вы можете добиться функциональности Автоустановленное событие, ManualResetEvent вручную установить событие, и Семафор, а также Ручка ожиданиястатические методы Подождите все и Подождите , пока.Более того, Подожди и Пульс может быть приемлемым в ситуациях, когда все дескрипторы ожидания требуют скупости. "

Мой вопрос в том, какова правильная интерпретация Последние приговор?

  • Ситуация с приличным / большим количеством дескрипторов ожидания, когда WaitOne() вызывается лишь изредка для какого-либо конкретного дескриптора ожидания.
  • Ситуация с приличным / большим количеством дескрипторов ожидания, когда редко более одного потока имеют тенденцию блокироваться для какого-либо конкретного дескриптора ожидания.
  • Какая-то другая интерпретация.

Также был бы признателен за разъяснение примеров таких ситуаций и, возможно, за то, как и / или почему они более эффективно обрабатываются с помощью Wait и Pulse, а не другими методами.

Спасибо!

Редактировать:Я нашел этот текст в Интернете здесь

Это было полезно?

Решение

Это говорит о том, что есть некоторые ситуации, когда Wait и Pulse обеспечивают более простое решение, чем дескрипторы wait.В общем, это происходит там, где:

  • Официант, а не уведомитель, решает, когда разблокировать
  • Условие блокировки включает в себя нечто большее, чем простой флаг (возможно, несколько переменных).

Вы все еще можете использовать дескрипторы ожидания в этих ситуациях, но ожидание / Импульс, как правило, проще.Самое замечательное в Wait / Pulse заключается в том, что Wait снимает базовую блокировку во время ожидания.Например, в следующем примере мы считываем _x и _y в пределах безопасности блокировки - и все же эта блокировка снимается во время ожидания, чтобы другой поток мог обновить эти переменные:

lock (_locker)
{
  while (_x < 10 && _y < 20) Monitor.Wait (_locker);
}

Затем другой поток может обновить _x и _y атомарно (в силу блокировки), а затем импульсно подать сигнал официанту:

lock (_locker)
{
  _x = 20;
  _y = 30;
  Monitor.Pulse (_locker);
} 

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

С точки зрения эффективности / потребления ресурсов (на что, я думаю, вы намекали), Wait / Pulse обычно быстрее и легче (поскольку имеет управляемую реализацию).Однако на практике это редко имеет большое значение.И на этом этапе Framework 4.0 включает управляемые версии ManualResetEvent и Semaphore с низкими накладными расходами (ManualResetEventSlim и SemaphoreSlim).

Framework 4.0 также предоставляет множество дополнительных опций синхронизации, которые уменьшают потребность в ожидании / импульсе:

  • Обратный отсчет
  • Барьер
  • PLINQ / Параллелизм данных (параллельный.Вызывать параллельно.For, Parallel.ForEach)
  • Задачи и продолжения

Все они намного более высокого уровня, чем Wait / Pulse, и IMO предпочтительнее для написания надежного и поддерживаемого кода (при условии, что они решат поставленную задачу).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top