Sobes.tech
Junior

Mi az a deadlock?

sobes.tech MI

Válasz az MI-től

Deadlock — ez egy holtponti helyzet több szálas programozásban, amikor két vagy több szál blokkolja egymást, várva az erőforrásokra, amelyeket más szálak foglalnak ebben a csoportban.

A deadlock kialakulásának feltételei (Koffman-féle feltételek):

  1. Kölcsönös kizárás (Mutual Exclusion): Az erőforrásokat nem lehet egyszerre több szállal használni.
  2. Tartás és várakozás (Hold and Wait): Azok a szálak, amelyek már rendelkeznek egy erőforrással, várnak egy további erőforrásra, amit egy másik szál foglal.
  3. Visszavonás hiánya (No Preemption): Az erőforrást nem lehet kényszeríteni egy szálból elvenni; csak a szál szabadon engedheti.
  4. Körkörös várakozás (Circular Wait): Két vagy több szál láncolata, ahol minden szál egy olyan erőforrást vár, amit a következő szál foglal.

Egyszerű példa deadlockra:

Két szál, két erőforrás (A és B).

  • Az 1. szál lefoglalja az A-t.
  • A 2. szál lefoglalja a B-t.
  • Az 1. szál megpróbálja lefoglalni a B-t (amelyet a 2. szál foglal).
  • A 2. szál megpróbálja lefoglalni az A-t (amelyet az 1. szál foglal).

Mindkét szál örökre blokkolva van.

// Egyszerű deadlock szimuláció lock használatával
object resourceA = new object();
object resourceB = new object();

void Thread1Method()
{
    lock (resourceA) // Az 1. szál lefoglalja az A-t
    {
        Console.WriteLine("Szál 1 lefoglalta az erőforrás A");
        Thread.Sleep(100); // Kis késleltetés a szálváltás demonstrálására
        lock (resourceB) // Az 1. szál megpróbálja lefoglalni a B-t
        {
            Console.WriteLine("Szál 1 lefoglalta az erőforrás B");
        }
    }
}

void Thread2Method()
{
    lock (resourceB) // A 2. szál lefoglalja a B-t
    {
        Console.WriteLine("Szál 2 lefoglalta az erőforrás B");
        Thread.Sleep(100); // Kis késleltetés
        lock (resourceA) // A 2. szál megpróbálja lefoglalni az A-t
        {
            Console.WriteLine("Szál 2 lefoglalta az erőforrás A");
        }
    }
}

// Szálak létrehozása és indítása deadlock-hoz vezethet.
// new Thread(Thread1Method).Start();
// new Thread(Thread2Method).Start();

// Ez a kód futtatásával előfordulhat, de nem feltétlenül, deadlock-ot mutatva,
// mivel a végrehajtási sorrend a ütemezőtől függ.
// Ha az 1. szál lefoglalja az A-t, és a 2. szál lefoglalja a B-t, mielőtt az első
// szál lefoglalná a B-t, deadlock alakul ki.

A deadlockok megelőzése gyakran a következőkkel érhető el:

  • Erőforrások foglalási sorrendjének egységesítése (mindig ugyanabban a sorrendben foglalni az erőforrásokat).
  • Időkorlátos foglalási módszerek alkalmazása (próbálja meg foglalni az erőforrást adott időn belül).
  • Olyan tervezés, amely nem igényli több zárolás egyidejű fenntartását.
  • Atom műveletek vagy magasabb szintű szinkronizációs primitívek használata (pl. Monitor.TryEnter, ReaderWriterLockSlim).

A deadlockokat nehéz hibakeresni, mivel a szálak végrehajtási sorrendjétől függenek, és gyakran csak terhelés alatt jelentkeznek. A Visual Studio eszközöket kínál ezek felismerésére és elemzésére.