Sobes.tech
Junior

Čo je deadlock?

sobes.tech AI

Odpoveď od AI

Deadlock je situácia slepého miesta v viacvláknovom programovaní, keď dve alebo viac vlákien blokujú navzájom, čakajúc na zdroje, ktoré sú obsadené inými vláknami v rovnakej skupine.

Podmienky vzniku deadlocku (Koffmanove podmienky):

  1. Vzájomné vylúčenie (Mutual Exclusion): Zdroje nemôžu byť používané súčasne viacerými vláknami.
  2. Držanie a čakanie (Hold and Wait): Vlákna, ktoré už majú jeden zdroj, čakajú na získanie ďalšieho zdroja, ktorý je obsadený iným vláknom.
  3. Žiadne predbehnutie (No Preemption): Zdroj nemôže byť vynútene odobraný vláknu, ktoré ho vlastní; môže byť uvoľnený iba samotným vláknom.
  4. Kruhové čakanie (Circular Wait): Existuje reťazec dvoch alebo viacerých vlákien, kde každé vlákno čaká na zdroj, ktorý vlastní nasledujúce vlákno v reťazci.

Jednoduchý príklad deadlocku:

Dve vlákna, dva zdroje (A a B).

  • Vlákno 1 získa zdroj A.
  • Vlákno 2 získa zdroj B.
  • Vlákno 1 sa pokúsi získať zdroj B (ktorý je obsadený vláknom 2).
  • Vlákno 2 sa pokúsi získať zdroj A (ktorý je obsadený vláknom 1).

Obe vlákna sú zablokované navždy.

// Jednoduchý príklad simulácie deadlocku s použitím lock
object resourceA = new object();
object resourceB = new object();

void Thread1Method()
{
    lock (resourceA) // Vlákno 1 získalo A
    {
        Console.WriteLine("Vlákno 1 získalo zdroj A");
        Thread.Sleep(100); // Malé zdržanie na demonštráciu možnosti prepínania vlákien
        lock (resourceB) // Vlákno 1 sa pokúsi získať B
        {
            Console.WriteLine("Vlákno 1 získalo zdroj B");
        }
    }
}

void Thread2Method()
{
    lock (resourceB) // Vlákno 2 získalo B
    {
        Console.WriteLine("Vlákno 2 získalo zdroj B");
        Thread.Sleep(100); // Malé zdržanie
        lock (resourceA) // Vlákno 2 sa pokúsi získať A
        {
            Console.WriteLine("Vlákno 2 získalo zdroj A");
        }
    }
}

// Vytvorenie a spustenie vlákien môže viesť k deadlocku.
// new Thread(Thread1Method).Start();
// new Thread(Thread2Method).Start();

// Spustenie tohto kódu môže, ale nie je nutné, demonštrovať deadlock,
// pretože poradie vykonávania závisí od plánovača.
// Ak vlákno 1 získa A a vlákno 2 získa B skôr, než prvé
// stihne získať B, vznikne deadlock.

Prevencia deadlockov sa často dosahuje:

  • Usporiadaním získavania zdrojov (vždy získať zdroje v rovnakom poradí).
  • Použitím metód získavania s časovým limitom (pokusit sa získať zdroj v určenom čase).
  • Navrhnutím bez potreby držať viac zámkov súčasne.
  • Použitím atomárnych operácií alebo vyšších úrovní primitivov na synchronizáciu (napr. Monitor.TryEnter, ReaderWriterLockSlim).

Deadlocky sú ťažko odhaľovateľné, pretože závisia od poradia vykonávania vlákien a často sa prejavujú iba pri zaťažení. Visual Studio poskytuje nástroje na ich detekciu a analýzu.