Ինչ է deadlock-ը goroutine-ով աշխատելիս;
sobes.tech AI
Պատասխան AI-ից
Deadlock (կապը խզում) — դա իրավիճակ է, երբ երկու կամ ավելի goroutine-ներ խափանում են միմյանց սպասելով, և ոչ մեկը չի կարող շարունակել իր կատարումը: Ամենից հաճախ դա տեղի է ունենում mutex-ների կամ ալիքների հետ աշխատելիս:
Deadlock-ի օրինակներ:
-
Mutex-ների խափանում տարբեր կարգով:
// Deadlock-ի օրինակ mutex-ներով var mu1 sync.Mutex var mu2 sync.Mutex func goroutine1() { mu1.Lock() // Հավաքում է mu1 time.Sleep(100 * time.Millisecond) // Կարճ սպասում mu2.Lock() // Փորձում է հավաքել mu2 (որը պահում է goroutine2) fmt.Println("goroutine1 ձեռք է բերել mu2") mu2.Unlock() mu1.Unlock() } func goroutine2() { mu2.Lock() // Հավաքում է mu2 time.Sleep(100 * time.Millisecond) // Կարճ սպասում mu1.Lock() // Փորձում է հավաքել mu1 (որը պահում է goroutine1) fmt.Println("goroutine2 ձեռք է բերել mu1") mu1.Unlock() mu2.Unlock() }Goroutine1-ը ձեռք է բերել
mu1և սպասում էmu2-ին: Goroutine2-ը ձեռք է բերելmu2և սպասում էmu1-ին: Երկուսն էլ խափանված են: -
Ուղարկում ոչ բուֆերային ալիքին առանց ընդունողի:
// Deadlock-ի օրինակ ալիքով func main() { ch := make(chan int) //go func() { // Եթե չսկսենք ընթերցող goroutine-ը, կլինի deadlock // <-ch //}() ch <- 1 // Ուղարկում ալիքին առանց ակտիվ ընդունողի fmt.Println("Ուղարկված ալիքին") // Այս տողը չի հասնի }Ուղարկումը ոչ բուֆերային ալիքին կխափանի, մինչև մյուս goroutine-ը սկսի կարդալ նրանից: Եթե ընդունող չկա, տեղի կունենա deadlock:
-
Կարդալ ալիքից առանց ուղարկողի (փակվելու կամ դատարկ բուֆերային):
// Deadlock-ի օրինակ ալիքից կարդալիս func main() { ch := make(chan int, 1) // Բուֆերային ալիք 1 տարրով ch <- 1 // Ուղարկեցինք 1 close(ch) // Փակեցինք ալիքին <-ch // Կարդացինք 1 <-ch // Փորձում ենք կրկին կարդալ փակ և դատարկ ալիքից - deadlock }Կարդալը փակված, դատարկ կամ բաց ալիքից հաջող կլինի: Կարդալը փակ և դատարկ կամ բաց, բայց դատարկ ոչ բուֆերային ալիքից առանց ուղարկողի հանգեցնում է բլոկավորման:
Golang ռունթայմը կարող է որոշակի deadlock-ների տեսակներ հայտնաբերել (օրինակ, երբ բոլոր խափանված goroutine-ները սպասում են միայն մեկ goroutine- ի ընդունմանը կամ ուղարկմանը), և այդ դեպքում ծրագիրը կավարտվի սխալի հաղորդագրությամբ "fatal error: all goroutines are asleep - deadlock!": Սակայն, ոչ բոլոր deadlock-ները կարող են ավտոմատ հայտնաբերվել:
Deadlock-ների կանխարգելման համար կարևոր է:
- Պահպանել կոնսիստենտ mutex-ների ձեռքբերման կարգը:
- Համոզվել, որ յուրաքանչյուր ոչ բուֆերային ալիքին ուղարկման համար կա համապատասխան կարդալ, և հակառակը:
- Կանալների հետ աշխատելիս օգտագործել
select-ըdefaultճյուղով կամ ժամանակային սահմանափակումներով: - Կանոնավոր կառավարել goroutine-ների կյանքի ցիկլը և ալիքների փակումը։