791
Операции.ввода-вывода.в.Windows
нации) будут обрабатываться в четырех потоках без
какого-либо переключения
контекста
1
.
Однако при блокировке потока (выполнении синхронной операции ввода-вы-
вода, вызове метода
Thread.Sleep
или ожидании, связанном с блокировкой потока
в рамках синхронизации потоков) Windows уведомляет пул о том, что один из его
потоков прекратил работу. Пул для восполнения недостаточной загрузки процес-
сора создает новый поток взамен заблокированного. К сожалению,
такой выход
из положения не идеален, потому что создание нового потока обходится довольно
дорого с точки зрения затрат времени и памяти.
Кроме того, позднее поток может быть разблокирован, и в итоге процессор
окажется перегруженным, что приведет к переключению контекста и снижению
производительности. Впрочем, эта проблема решается средствами пула. Завер-
шившим
свою работу потокам, которые вернулись в пул, не дают обрабатывать
новые элементы, пока загрузка процессора не достигнет определенного уровня.
Таким способом уменьшается количество переключений контекста и повышается
производительность. Если впоследствии пул обнаружит, что потоков больше, чем
необходимо, он просто позволит лишним потокам самоуничтожиться, освободив
ресурсы.
Для реализации описанного поведения CLR-пул
потоков использует такой
ресурс Windows, как
порт завершения ввода-вывода
(I/O Completion Port). Он
создается при инициализации CLR. Затем с этим портом можно связать подсо-
единяемые устройства, чтобы в результате их драйверы «знали», куда поставить в
очередь IRP-пакет. Подробнее этот механизм описан в моей книге «Windows via
C/C++» (Microsoft Press, 2007).
Асинхронный ввод-вывод кроме минимального использования ресурсов и умень-
шения количества переключений контекста предоставляет и другие преимущества.
Скажем, в начале сборки мусора CLR приостанавливает все потоки в процессе.
Получается, чем меньше у нас потоков, тем быстрее произойдет уборка мусора.
Кроме того, при уборке мусора CLR просматривает в поисках корней все стеки по-
токов. Соответственно,
чем меньше у нас потоков, тем меньше стеков приходится
просматривать и тем быстрее работает уборщик мусора. Плюс ко всему, если в про-
цессе обработки потоки не были заблокированы, большую часть времени они будут
1
Предполагается, что другие потоки в это время отсутствуют. Большую часть времени
действительно так, ведь большинство компьютеров не задействует процессор на 100 %.
Однако даже при полной загрузке процессора все будет
работать описанным образом, если
исполняемые потоки имеют низкие приоритеты. Наличие других потоков приводит к пере-
ключениям контекста. Это плохо с точки зрения производительности, но хорошо с точки
зрения надежности. Напоминаю, что Windows выделяет на каждый процесс по крайней
мере один поток и переключает контекст, гарантируя, что даже
блокировка одного потока
не остановит работу приложения.