Sobes.tech
Middle+

Czym jest livelock?

sobes.tech AI

Odpowiedź od AI

Livelock to stan, w którym wątki próbują nieustannie wykonać pracę, anulując nawzajem swoje działania z powodu rywalizacji o zasoby, co uniemożliwia im postęp.

Przykład livelock: dwa wątki próbują uzyskać dwa zasoby A i B. Wątek 1:

  1. Uzyskuje zasób A.
  2. Próbuje uzyskać zasób B. Jeśli się nie uda, zwalnia A i zaczyna od nowa.

Wątek 2:

  1. Uzyskuje zasób B.
  2. Próbuje uzyskać zasób A. Jeśli się nie uda, zwalnia B i zaczyna od nowa.

W rezultacie wątki mogą ciągle zwalniać zasoby i próbować je ponownie uzyskać, nie osiągając celu.

Różnice z deadlockiem:

  • Deadlock: wątki są zablokowane, oczekując na siebie nawzajem.
  • Livelock: wątki aktywnie pracują, ale nie postępują.

Zapobieganie:

  • Uporządkowany dostęp do zasobów.
  • Limit czasowy przy próbie uzyskania zasobu.
  • Unikanie skomplikowanych zależności między zasobami.

Przykład pseudokodu z próbą livelock:

// Zasób 1
let resource1 = NSLock()
// Zasób 2
let resource2 = NSLock()

// Wątek 1
DispatchQueue.global().async {
    while true {
        resource1.lock()
        if resource2.tryLock() {
            // Oba zasoby uzyskane pomyślnie
            // Wykonanie pracy
            print("Wątek 1 wykonuje pracę")
            resource2.unlock()
            resource1.unlock()
            break // Zakończenie po sukcesie
        } else {
            // Nie udało się uzyskać resource2, zwolnij resource1 i spróbuj ponownie
            resource1.unlock()
            // Krótka przerwa, aby uniknąć natychmiastowych prób
            Thread.sleep(forTimeInterval: 0.01)
        }
    }
}

// Wątek 2
DispatchQueue.global().async {
    while true {
        resource2.lock()
        if resource1.tryLock() {
            // Oba zasoby uzyskane pomyślnie
            // Wykonanie pracy
            print("Wątek 2 wykonuje pracę")
            resource1.unlock()
            resource2.unlock()
            break // Zakończenie po sukcesie
        } else {
            // Nie udało się uzyskać resource1, zwolnij resource2 i spróbuj ponownie
            resource2.unlock()
            // Krótka przerwa
            Thread.sleep(forTimeInterval: 0.01)
        }
    }
}