Sobes.tech
Junior

Kas ir deadlock?

sobes.tech AI

Atbilde no AI

Dēdlocks — tas ir aizsērējis stāvoklis daudzķermeņu programmēšanā, kad divi vai vairāk pavedieni bloķē viens otru, gaidot resursus, kas ir aizņemti citiem pavedieniem tajā pašā grupā.

Dēdlocka rašanās nosacījumi (Kofmana nosacījumi):

  1. Savstarpēja izslēgšana (Mutual Exclusion): Resursi nevar tikt izmantoti vienlaicīgi vairākām pavedieniem.
  2. Turēšana un gaidīšana (Hold and Wait): Pavedieni, kuri jau ir ieguvuši vienu resursu, gaida papildu resursu, ko aizņem cits pavediens.
  3. Bez atņemšanas (No Preemption): Resurss nevar tikt piespiedu kārtā atņemts pavedienam, kurš to tur; tas var tikt atbrīvots tikai pats pavediens.
  4. Apļveida gaidīšana (Circular Wait): Pastāv ķēde no diviem vai vairāk pavedieniem, kur katrs gaida resursu, ko tur nākamais ķēdes pavediens (būtībā, gaidīšana "apļveidā").

Vienkāršs piemērs dēdlockam:

Divi pavedieni, divi resursi (A un B).

  • Pavediens 1 ieņem resursu A.
  • Pavediens 2 ieņem resursu B.
  • Pavediens 1 mēģina ieņemt resursu B (kas ir aizņemts Pavediena 2).
  • Pavediens 2 mēģina ieņemt resursu A (kas ir aizņemts Pavediena 1).

Abi pavedieni ir mūžīgi bloķēti.

// Vienkāršs dēdlock simulācijas piemērs, izmantojot lock
object resourceA = new object();
object resourceB = new object();

void Thread1Method()
{
    lock (resourceA) // Pavediens 1 ieņem A
    {
        Console.WriteLine("Pavediens 1 ieņēma resursu A");
        Thread.Sleep(100); // Neliela aizkave, lai parādītu iespēju pārslēgt pavedienus
        lock (resourceB) // Pavediens 1 mēģina ieņemt B
        {
            Console.WriteLine("Pavediens 1 ieņēma resursu B");
        }
    }
}

void Thread2Method()
{
    lock (resourceB) // Pavediens 2 ieņem B
    {
        Console.WriteLine("Pavediens 2 ieņēma resursu B");
        Thread.Sleep(100); // Neliela aizkave
        lock (resourceA) // Pavediens 2 mēģina ieņemt A
        {
            Console.WriteLine("Pavediens 2 ieņēma resursu A");
        }
    }
}

// Pavedienu izveide un palaišana var novest pie dēdlocka.
// new Thread(Thread1Method).Start();
// new Thread(Thread2Method).Start();

// Šīs koda izpilde var, bet nav obligāta, parādīt dēdlocku,
// jo izpildes kārtība ir atkarīga no plānotāja.
// Ja Pavediens 1 ieņem A, bet Pavediens 2 ieņem B, pirms pirmā
// spēj ieņemt B, notiks dēdlocks.

Dēdlocku novēršana bieži tiek panākta ar:

  • Resursu ieguves secības sakārtošanu (vienmēr iegūt resursus tajā pašā secībā).
  • Laika ierobežotas resursu iegūšanas metodes izmantošanu (mēģināt iegūt resursu noteiktā laikā).
  • Projektēšanu bez nepieciešamības turēt vairākus bloķējumus vienlaicīgi.
  • Atomāro operāciju vai augstākā līmeņa sinhronizācijas primitīvu izmantošanu (piemēram, Monitor.TryEnter, ReaderWriterLockSlim).

Dēdlocki ir grūti diagnosticējami, jo tie ir atkarīgi no pavedienu izpildes secības un bieži parādās tikai slodzes laikā. Visual Studio nodrošina rīkus to atklāšanai un analīzei.