Junior
Kas yra deadlock?
sobes.tech AI
Atsakymas iš AI
Dėdlokas — tai užstrigimo situacija daugiasraityje programavime, kai du ar daugiau srautų blokuoja vienas kitą, laukdami išteklių, kurie yra užimti kitų tėkų iš tos pačios grupės.
Dėdloko sąlygos (Kofmano sąlygos):
- Tarpusavio išskirtinumas (Mutual Exclusion): Ištekliai negali būti naudojami vienu metu kelių srautų.
- Laikymas ir laukimas (Hold and Wait): Turėdami vieną išteklių, srautai laukia papildomo išteklio, kurį užima kitas srautas.
- Be atėmimo (No Preemption): Išteklis negali būti prievarta atimtas iš srauto, kuris juo disponuoja; jis gali būti atlaisvintas tik pats srautas.
- Apytikslis laukimas (Circular Wait): Yra grandinė iš dviejų ar daugiau srautų, kur kiekvienas laukia išteklio, kurį turi kitas grandinės srautas (iš esmės, laukimas "aplinkui").
Paprastas dėdloko pavyzdys:
Du srautai, du ištekliai (A ir B).
- Srautas 1 užima išteklių A.
- Srautas 2 užima išteklių B.
- Srautas 1 bando užimti išteklių B (kuris yra užimtas Srauto 2).
- Srautas 2 bando užimti išteklių A (kuris yra užimtas Srauto 1).
Abu srautai yra amžinai užrakinti.
// Paprastas dėdloko simuliacijos pavyzdys naudojant lock
object resourceA = new object();
object resourceB = new object();
void Thread1Method()
{
lock (resourceA) // Srautas 1 užėmė A
{
Console.WriteLine("Srautas 1 užėmė išteklių A");
Thread.Sleep(100); // Mažas delsa, norint parodyti galimybę perjungti srautus
lock (resourceB) // Srautas 1 bando užimti B
{
Console.WriteLine("Srautas 1 užėmė išteklių B");
}
}
}
void Thread2Method()
{
lock (resourceB) // Srautas 2 užėmė B
{
Console.WriteLine("Srautas 2 užėmė išteklių B");
Thread.Sleep(100); // Mažas delsa
lock (resourceA) // Srautas 2 bando užimti A
{
Console.WriteLine("Srautas 2 užėmė išteklių A");
}
}
}
// Srautų sukūrimas ir paleidimas gali sukelti dėdloką.
// new Thread(Thread1Method).Start();
// new Thread(Thread2Method).Start();
// Šio kodo paleidimas gali, bet nebūtinai, parodyti dėdloką,
// nes vykdymo tvarka priklauso nuo planuotojo.
// Jei Srautas 1 užims A, o Srautas 2 užims B, kol pirmas
// nepavyks užimti B, įvyks dėdlokas.
Dėdloko prevencija dažnai pasiekiama:
- Rūšiuojant išteklių įgijimo tvarką (visada įgyti išteklius toje pačioje tvarkoje).
- Naudojant laiko limituotas išteklių įgijimo metodus (bandyti įgyti išteklių tam tikru laiku).
- Projektuojant be poreikio vienu metu laikyti kelias užrakinimo priemones.
- Naudojant atomines operacijas arba aukštesnio lygio sinchronizacijos primitivius (pvz.,
Monitor.TryEnter,ReaderWriterLockSlim).
Dėdlokai yra sunkiai diagnozuojami, nes priklauso nuo srautų vykdymo tvarkos ir dažnai pasireiškia tik apkrovos metu. Visual Studio siūlo įrankius jų aptikimui ir analizei.