В чем разница между Deadlock и Livelock в многопоточном программировании?

Ответ

Deadlock (взаимная блокировка) — это состояние, при котором два или более потока/процесса навсегда заблокированы, ожидая ресурсы, удерживаемые друг другом. Ни один из них не может продолжить выполнение.

Livelock (активная блокировка) — состояние, при котором потоки не блокируются полностью, а продолжают выполнять работу (например, освобождать и повторно захватывать ресурсы), но не продвигаются к завершению из-за циклической реакции друг на друга.

Ключевое отличие: При deadlock потоки пассивно ожидают, при livelock — активно, но безуспешно работают.

Пример Deadlock (Swift/Foundation):

let lock1 = NSLock()
let lock2 = NSLock()

DispatchQueue.global().async {
    lock1.lock()
    Thread.sleep(forTimeInterval: 0.1)
    lock2.lock() // Блокировка: lock2 удерживается другим потоком
    // Критическая секция
    lock2.unlock()
    lock1.unlock()
}

DispatchQueue.global().async {
    lock2.lock()
    Thread.sleep(forTimeInterval: 0.1)
    lock1.lock() // Блокировка: lock1 удерживается другим потоком
    // Критическая секция
    lock1.unlock()
    lock2.unlock()
}

Пример Livelock (концептуальный):

Два потока пытаются избежать deadlock, освобождая ресурс при обнаружении конфликта, но делают это синхронно, попадая в бесконечный цикл «уступить-проверить-повторить».

Практические меры предотвращения:

  • Упорядоченный захват ресурсов (всегда в одном порядке).
  • Использование tryLock с таймаутом.
  • Проектирование алгоритмов без циклических зависимостей.

Ответ 18+ 🔞

А, слушай, вот эта тема про deadlock и livelock — это ж классика, прямо как в жизни, блядь. Один другого ждёт, а тот, сука, тоже ждёт, и оба в итоге нихуя не делают, застыли как идиоты. Или ещё хуже — оба суетятся, как мартышки, но с места ни на сантиметр.

Deadlock (взаимная блокировка) — это когда два потока, или больше, намертво встали в позу, ёпта. Каждый держит в лапах какую-то нужную хуйню и ждёт, пока другой свою отпустит. А тот, блядь, тоже ждёт. И так до скончания века, пока систему не перезагрузят. Полный пиздец и тишина.

Livelock (активная блокировка) — это поинтереснее, блядь. Тут они не засыпают, нет. Они как те два вежливых мудака в дверном проёме: «Ах, нет, вы первый!», «Нет, я настаиваю, вы!». Шагают туда-сюда, суетятся, ресурсы отпускают и хватают обратно, но нихуя не продвигаются. Работа кипит, а результата — ноль, ебать мои старые костыли.

Ключевое отличие, блядь: При deadlock — тишина, сопли на кулак намотали и ждут. При livelock — адская дискотека, все в движении, но тоже в пизду.

Пример Deadlock (Swift/Foundation):

Смотри, какая простая и ебейшая ситуация. Два потока, два замка. Как в плохом анекдоте.

let lock1 = NSLock()
let lock2 = NSLock()

DispatchQueue.global().async {
    lock1.lock() // Первый чувак схватил первый замок
    Thread.sleep(forTimeInterval: 0.1) // Немного подрыхнул, блядь
    lock2.lock() // А тут пиздец: он тянется за вторым, но его уже держит второй поток!
    // До этой строчки он никогда, блядь, не доберётся
    lock2.unlock()
    lock1.unlock()
}

DispatchQueue.global().async {
    lock2.lock() // Второй чувак, хитрая жопа, сразу взял второй замок
    Thread.sleep(forTimeInterval: 0.1) // Тоже решил вздремнуть
    lock1.lock() // Ага, попробуй-ка взять первый, который уже в лапах у первого! Засада!
    // И этот тоже навеки застрял
    lock1.unlock()
    lock2.unlock()
}

Вот и всё. Система повисла. Два потока смотрят друг на друга пустыми глазами и держат свои замки до гроба. Классический deadlock, ёперный театр.

Пример Livelock (концептуальный):

Ну, представь, блядь, два алгоритма, которые слишком умные. Видят, что ресурс занят, и такие: «О, нехорошо, deadlock намечается! Надо вежливо отступить!». Отступают оба одновременно. Потом снова лезут. Опять сталкиваются. Снова отступают. И так до овердохуища. Движение есть, прогресса — нихуя. Вежливость до добра не доводит, вот в чём парадокс.

Практические меры, чтобы не облажаться:

  • Захватывай ресурсы в одном порядке, блядь. Всегда сначала lock1, потом lock2. Как в армии: «По росту строись!». Тогда цикла не будет.
  • Используй tryLock с таймаутом. Не можешь взять — не стой как истукан, пойди, другие дела поделай, а потом вернись. Не упрямься, как мудак.
  • Проектируй алгоритмы без циклических пизделок. Чтобы никто ни от кого не зависел по кругу. Это, конечно, высший пилотаж, но стремиться надо.

Вот и вся наука. Либо тихо сдохнешь в deadlock, либо загнешься с улыбкой в livelock. Выбирай, блядь. Главное — проектируй так, чтобы избежать и того, и другого.