Goroutine менен иштөөдө deadlock эмне?
sobes.tech AI
AIден жооп
Deadlock (талаа) — бул эки же көп горутиналар бири-бирин күтүп, блоктоло турган абал. Адатта, бул 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ти күтүп жатат. Goroutine2mu2ти алды жанаmu1ти күтүп жатат. Эки goroutine да блоктогон. -
Набор в небуферизованный канал без получателя:
// 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-дун рунтаймы белгилүү түрлөрүн аныктай алат (мисалы, бардык блоктогон goroutine-лер бир гана goroutine-дин кабыл алуу же жөнөтүү күтүп жатса), жана мындай учурда программа күтүүсүздөн "fatal error: all goroutines are asleep - deadlock!" деген билдирүү менен аяктайт. Бирок, бардык deadlock-лор автоматтык түрдө аныктала бербейт.
Deadlock-лорду алдын алуу үчүн маанилүү:
- mutexтерди бирдиктүү тартипте алуу;
- ар бир небуферизованный каналга жөнөтүү үчүн тиешелүү окуу бар экенине көз жеткізүү;
- каналдар менен иштөөдө
selectжанаdefaultбөлүмдөрүн колдонуу; - goroutine-лердин жашоо циклин жана каналдарды жабууну так башкаруу.