Junior
Co je to deadlock?
sobes.tech AI
Odpověď od AI
Deadlock je situace slepé uličky v multithreadovém programování, kdy dva nebo více vláken blokují navzájem, čekajíce na zdroje, které jsou obsazeny jinými vlákny ve stejné skupině.
Podmínky vzniku deadlocku (Koffmanovy podmínky):
- Vzájemné vyloučení (Mutual Exclusion): Zdroje nemohou být používány současně více vlákny.
- Držení a čekání (Hold and Wait): Vlákna, která již mají jeden zdroj, čekají na získání dalšího zdroje, který je obsazen jiným vláknem.
- Žádné předběhnutí (No Preemption): Zdroj nemůže být vynuceně odebrán vláknu, které jím disponuje; může být uvolněn pouze samotným vláknem.
- Kruhové čekání (Circular Wait): Existuje řetězec dvou nebo více vláken, kde každé vlákno čeká na zdroj, který vlastní následující vlákno v řetězci (v podstatě čekání "v kruhu").
Jednoduchý příklad deadlocku:
Dvě vlákna, dva zdroje (A a B).
- Vlákno 1 získá zdroj A.
- Vlákno 2 získá zdroj B.
- Vlákno 1 se pokusí získat zdroj B (který je obsazen Vlákem 2).
- Vlákno 2 se pokusí získat zdroj A (který je obsazen Vlákem 1).
Obě vlákna jsou navždy zablokována.
// Jednoduchá simulace 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é zpoždění pro demonstraci možnosti přepínání vláken
lock (resourceB) // Vlákno 1 se pokusí získat 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é zpoždění
lock (resourceA) // Vlákno 2 se pokusí získat A
{
Console.WriteLine("Vlákno 2 získalo zdroj A");
}
}
}
// Vytvoření a spuštění vláken může vést k deadlocku.
// new Thread(Thread1Method).Start();
// new Thread(Thread2Method).Start();
// Spuštění tohoto kódu může, ale nemusí, demonstrovat deadlock,
// protože pořadí provádění závisí na plánovači.
// Pokud vlákno 1 získá A a vlákno 2 získá B dříve, než první
// stihne získat B, vznikne deadlock.
Prevence deadlocků se často dosahuje:
- Uspořádáním získávání zdrojů (vždy získávat zdroje ve stejném pořadí).
- Použitím metod získávání s časovým limitem (pokusit se získat zdroj během určitého času).
- Navržením bez nutnosti držet více zámků současně.
- Použitím atomárních operací nebo vyšších synchronizačních primitivů (například
Monitor.TryEnter,ReaderWriterLockSlim).
Deadlocky jsou obtížné ladit, protože závisí na pořadí provádění vláken a často se projevují pouze při zátěži. Visual Studio nabízí nástroje pro jejich detekci a analýzu.