874
Глава.30 .Гибридные.конструкции.синхронизации.потоков
управления. Разумеется, блокировка GUI-потока подвешивает приложение
и мешает работе пользователя.
Чтобы избежать блокировки потоков, не стоит мысленно связывать их с кон-
кретными операциями. К примеру, не нужно создавать поток, проверяющий орфо-
графию, поток,
проверяющий грамматику, поток, обрабатывающий определенные
клиентские запросы и т. п. Потому что подобный подход как бы показывает, что
поток не может выполнять других операций. Однако потоки являются слишком
ценным ресурсом, чтобы ограничивать их только одной операцией. Используйте
пул для аренды потоков на короткий период времени. Поток из пула может начать
с проверки орфографии, затем перейти к проверке грамматики, затем заняться об-
работкой клиентских запросов и т. п.
Если же вы, несмотря ни на что,
решите блокировать потоки, для синхронизации
потоков из разных доменов или процессов используйте конструкции режима ядра.
Для атомарного управления состоянием через набор операций вам потребуется класс
Monitor
с закрытым полем
1
. В качестве альтернативы можно прибегнуть к блоки-
рованию на чтение-запись. В общем случае это блокирование работает медленнее
класса
Monitor
, но оно позволяет одновременно исполняться нескольким потокам
чтения, что повышает общую производительность и минимизирует возможность
блокировки потоков.
Также старайтесь избегать рекурсивных блокировок (особенно блокировок
чтения-записи), так как они серьезно снижают производительность. Впрочем,
класс
Monitor
,
несмотря на свою рекурсивность, показывает высокую произво-
дительность
2
. Кроме того, старайтесь не снимать блокировку в блоке
finally
, так
как вход в блоки обработки исключений и выход из них негативно сказывается на
производительности. Кроме того, выдача исключения при изменении состояния
приводит к ситуации, когда другим потокам приходится работать с поврежденными
данными, из-за чего результат работы приложения
становится непредсказуемым
и возникают бреши в системе безопасности.
И, разумеется, если ваш код все-таки удерживает блокировку, он не должен
удерживать ее слишком долго, так как в результате повышается вероятность бло-
кирования потоков. Далее будет показана техника работы с классами коллекций,
позволяющая избежать длительного удерживания блокировки.
Ну и, наконец, для вычислительных операций можно использовать задания (о ко-
торых мы говорили в главе 27), чтобы обойтись без многочисленных конструкций
синхронизации. В частности, мне нравится, что с каждым заданием можно связать
1
Вместо класса Monitor можно воспользоваться чуть более быстрым классом SpinLock.
Но при этом возможна ситуация, когда ресурсы процессора начнут тратиться впустую. И с
моей точки зрения, класс SpinLock не настолько превосходит
Monitor по скорости, чтобы
оправдать его применение.
2
Частично это связано с тем, что класс Monitor реализован на машинном, а не на управ-
ляемом коде.
875
Блокировка.с.двойной.проверкой
одно или несколько других заданий, которые начинают выполняться средствами
пула потоков при завершении некой операции. Это намного лучше,
чем блокировать
поток, ожидая завершения операции. Для операций ввода-вывода следует вызывать
различные методы
XxxAsync
, которые заставляют ваш код продолжать выполнение
после завершений операций ввода-вывода (аналог заданий, выполняемых по за-
вершению операции).
Do'stlaringiz bilan baham: