Ответ
Deadlock (взаимная блокировка) — это ситуация в многопоточном программировании, когда два или более потока находятся в состоянии бесконечного ожидания ресурсов, захваченных друг другом. Ни один из потоков не может продолжить выполнение.
Классический пример на C#:
object lockA = new object();
object lockB = new object();
Thread thread1 = new Thread(() => {
lock (lockA) {
Thread.Sleep(100);
// Поток 1 ждёт lockB, который удерживается потоком 2
lock (lockB) {
Console.WriteLine("Thread1 completed");
}
}
});
Thread thread2 = new Thread(() => {
lock (lockB) {
Thread.Sleep(100);
// Поток 2 ждёт lockA, который удерживается потоком 1
lock (lockA) {
Console.WriteLine("Thread2 completed");
}
}
});
thread1.Start();
thread2.Start();
// Оба потока зависнут.
Условия возникновения (Коффмана):
- Взаимное исключение: ресурс не может использоваться более чем одним потоком одновременно.
- Удержание и ожидание: поток удерживает один ресурс и ждёт другой.
- Отсутствие вытеснения: ресурс нельзя отобрать у потока, только добровольно освободить.
- Циклическое ожидание: потоки образуют замкнутый цикл ожидания ресурсов.
Стратегии предотвращения:
- Упорядочивание блокировок: Всегда захватывать блокировки в строго определённом глобальном порядке (например, сначала
lockA, потомlockB). - Использование таймаутов:
Monitor.TryEnter(lockObj, TimeSpan)илиSemaphoreSlim.Wait(TimeSpan)для выхода из ожидания. - Уменьшение времени удержания блокировки: Выполнять внутри
lockтолько минимально необходимые операции. - Проектирование без блокировок: Использование потокобезопасных коллекций (
ConcurrentBag,ConcurrentDictionary),async/awaitдля I/O операций или модели акторов. - Статический анализ: Инструменты вроде
Microsoft.ConcurrencyVisualizerилиRoslyn-анализаторы для поиска потенциальных deadlock'ов.
Видео-ответы
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶