← Назад к вопросам

Что такое LiveLock?

1.7 Middle🔥 21 комментариев
#Многопоточность и асинхронность

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое LiveLock?

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

Ключевые различия LiveLock и DeadLock

  • DeadLock: потоки полностью блокируются, ожидают ресурсы и не выполняют никакой работы.
  • LiveLock: потоки активны, выполняют код, но их действия не приводят к прогрессу из-за повторяющихся неудачных попыток.

Пример в контексте iOS разработки

Рассмотрим классический сценарий с двумя потоками, пытающимися захватить два ресурса (A и B) с использованием "политики вежливости" (например, при неудачной попытке отпускают ресурс и повторяют):

import Foundation

class Resource {
    let lock = NSLock()
}

let resourceA = Resource()
let resourceB = Resource()

DispatchQueue.global().async {
    while true {
        if resourceA.lock.try() {
            if resourceB.lock.try() {
                print("Thread 1 acquired both resources")
                // Выполняем работу
                resourceB.lock.unlock()
                resourceA.lock.unlock()
                break
            } else {
                resourceA.lock.unlock() // "Вежливо" отпускаем A
                print("Thread 1 released A, retrying...")
            }
        }
        // Небольшая задержка перед повторной попыткой
        usleep(100)
    }
}

DispatchQueue.global().async {
    while true {
        if resourceB.lock.try() {
            if resourceA.lock.try() {
                print("Thread 2 acquired both resources")
                // Выполняем работу
                resourceA.lock.unlock()
                resourceB.lock.unlock()
                break
            } else {
                resourceB.lock.unlock() // "Вежливо" отпускаем B
                print("Thread 2 released B, retrying...")
            }
        }
        usleep(100)
    }
}

В этом примере возможна ситуация LiveLock:

  • Поток 1 захватывает A, но не может захватить B → отпускает A.
  • Поток 2 захватывает B, но не может захватить A → отпускает B.
  • Затем они повторяют попытки в том же порядке, бесконечно "танцуя" вокруг ресурсов.

Типичные причины LiveLock в iOS

  1. Неадекватные стратегии разрешения конфликтов: "Вежливые" алгоритмы, которые отпускают ресурсы при конфликте, могут привести к цикличности.
  2. Некорректная обработка ошибок в асинхронных операциях: Например, повторные попытки сетевых запросов при постоянных ошибках без изменения параметров.
  3. Конкуренция за общие данные без прогресса: Потоки постоянно изменяют состояние объекта, но не достигают стабильного условия для завершения.

Как предотвратить LiveLock

  • Использование очередей (DispatchQueue) и сериализации: вместо прямого управления блокировками.
  • Применение гарантированных стратегий захвата ресурсов: например, фиксированный порядок захвата (всегда сначала A, затем B).
  • Введение случайных или приоритетных задержек между повторными попытками.
  • Отказ от "вежливых" алгоритмов в пользу блокировок с ожиданием (например, NSLock с lock() вместо try()).
  • Мониторинг прогресса операции: если попытки повторяются без результата N раз, изменить стратегию.

Практический совет для iOS разработчиков

В iOS чаще возникают проблемы с DeadLock (например, в Grand Central Dispatch при неправильном использованию sync на текущей очереди), но LiveLock возможен в сложных сценариях с повторными попытками и конкурентными операциями. Рекомендуется использовать асинхронные паттерны (async/await в Swift) и готовые механизмы координации (DispatchGroup, OperationQueue с зависимостями), которые минимизируют риск обеих проблем.

LiveLock — менее очевидная, но опасная проблема, поскольку система остаётся "живой", но фактически не работает, что может скрываться в метриках и логировании.