Про экономию сигналов

Посмотрим еще раз на добавление задачи в очередь:

lock (locker) { taskQ.Enqueue(task); Monitor.PulseAll(locker); }

Вообще говоря, можно было сэкономить на выдаче сигналов, сигналя только тогда, когда действительно есть возможность освободить блокированного исполнителя:

lock (locker) { taskQ.Enqueue(task); if (taskQ.Count <= workers.Length) Monitor.PulseAll(locker); }

Сэкономим мы, однако, немного, так как выдача сигнала занимает менее микросекунды и не влечет за собой накладных расходов для занятых потребителей, поскольку они этот сигнал все равно игнорируют. Правильной практикой для многопоточного кода будет удаление любой необязательной логики: плохо воспроизводимый дефект из-за глупой ошибки – слишком большая цена за экономию одной микросекунды! Вот пример внесения блуждающей ошибки типа “застрявший потребитель”, которая наверняка не будет выявлена при первоначальном тестировании (найди одно отличие):

lock (locker) { taskQ.Enqueue(task); if (taskQ.Count < workers.Length) Monitor.PulseAll(locker); }

Сигнализация без всяких условий защитит вас от этого типа ошибок.

СОВЕТ Сомневаешься – сигналь! В рассмотренном шаблоне проектирования сигнализация редко может повредить.

Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: