10.1.1. Нежелательное блокирование
Что я понимаю под нежелательным блокированием? Прежде всего, поток считается заблокированным, если он не может продолжать выполнение, так как чего-то ждет. Это что-то может быть мьютексом, условной переменной, будущим результатом или завершением ввода/вывода. Это естественный, но не всегда приветствуемый аспект многопоточного кода, потому мы и говорим о проблеме нежелательного блокирования. Тогда возникает следующий вопрос: почему блокирование нежелательно? Обычно потому, что какой-то другой поток ждет результатов от заблокированного потока, чтобы выполнить некоторую операцию. И, значит, этот поток также оказывается заблокированным. На эту тему есть различные вариации.
• Взаимоблокировка — в главе 3 мы видели, что взаимоблокировка возникает, когда один поток ждет другого, а тот, в свою очередь, ждет первого. Если потоки взаимно блокируют друг друга, то порученные им задачи вообще никогда не будут выполнены. Наиболее наглядно это проявляется, когда один из таких потоков отвечает за пользовательский интерфейс; в этом случае интерфейс просто перестаёт реагировать на действия пользователя. В других случаях интерфейс реагирует, но какая-то задача не может завершиться, например, поиск не возвращает результатов или документ не печатается.
• Активная блокировка — похожа на взаимоблокировку в том смысле, что один поток ждет другого, а тот ждет первого. Но ключевое отличие заключается в том, что здесь мы имеем не блокирующее ожидание, а цикл активной проверки, например спинлок. В серьезных случаях симптомы выглядят так же, как при взаимоблокировке (приложение не может продолжить работу), только программа потребляет много процессорного времени, потому что потоки блокируют друг друга, продолжая работать. В менее серьезных случаях активная блокировка рано или поздно «рассасывается» из-за вероятностной природы планирования, но заблокированная задача испытывает ощутимые задержки, характеризуемые высоким потреблением процессорного времени.
• Блокировка в ожидании завершения ввода/вывода или поступления данных из внешнего источника — если поток блокируется в ожидании данных из внешнего источника, то он не может продолжать работу, даже если данные так никогда и не поступят. Поэтому крайне нежелательно, когда такая блокировка происходит в потоке, от работы которого зависят другие потоки.
Вот вкратце описание нежелательного блокирования. А как насчет состояний гонки?