GoDasturchi
Case Study: The Goroutine That Never Finishes

Case Study: The Goroutine That Never Finishes

Amaliy holat: hech qachon tugamaydigan goroutine

Ikki odamni tasavvur qiling: ular telefon orqali gaplashishga kelishgan, lekin ikkalasi ham "sen birinchi qo'ng'iroq qil" deb, IKKALASI ham kutib turibdi — hech biri birinchi bo'lib qo'ng'iroq qilmaydi. Ular ABADIY shu holatda qolishlari mumkin, chunki har biri boshqasining harakatini kutmoqda. Bu — dasturlashdagi deadlock yoki "hech qachon tugamaydigan kutish"ning aniq tasviri.

Stsenariy: sizning dasturingiz ba'zan "osilib qoladi" — hech qanday xato bermaydi, lekin ham hech narsa qilmaydi, dastur to'xtab qoladi. go tool pprof yoki oddiy kuzatuv orqali, siz goroutine'lar soni VAQT O'TISHI bilan doimiy o'sib borayotganini ko'rasiz — ular ochiladi, lekin hech qachon yopilmaydi.

worker.go
func processInBackground(jobs <-chan Job) {
	results := make(chan Result) // buferlanmagan kanal

	for job := range jobs {
		go func(j Job) {
			result := doWork(j)
			results <- result // bu yerda hech kim tinglamasa, abadiy kutadi
		}(job)
	}
}

Concurrency Fundamentals kursida ko'rgan buferlanmagan (unbuffered) kanal — yuboruvchi va qabul qiluvchi BIR VAQTDA "tayyor" bo'lishini talab qiladi. Bu kodda har bir job uchun yangi goroutine ishga tushiriladi, u ishni bajarib, natijani results kanaliga yubormoqchi bo'ladi — LEKIN hech kim results kanalidan O'QIMAYDI. Har bir goroutine results <- result qatorida ABADIY kutib qoladi.

  • Guessing vs Forming a Hypothesis darsidagi kabi gipoteza: "agar goroutine'lar soni cheksiz o'ssa va hech qachon kamaymasa, demak ular biror joyda BLOKLANIB qolyapti, hech qachon tugamayapti"
  • Har bir yangi job — yangi goroutine yaratadi, lekin processInBackground funksiyasi natijalarni HECH QACHON o'qimaydi — kanal faqat yozish uchun ishlatiladi, o'qish uchun emas
  • Reading a Stack Trace darsidagi kabi: dastur "osilib qolganda" Go'ning SIGQUIT signali (yoki debugger) orqali BARCHA goroutine'larning stack trace'ini olsa, ko'plab goroutine aynan shu results <- result qatorida to'xtab qolganini ko'rasiz

Sabab topildi: results kanaliga yozilgan qiymatlarni hech kim o'qimaydi, shuning uchun har bir yozuvchi goroutine ABADIY bloklanib qoladi — hech qachon tugamaydi, hech qachon xotiradan chiqmaydi. Yechim — yo natijalarni o'qiydigan alohida "yig'uvchi" goroutine qo'shish, yo results kanalini butunlay olib tashlab, agar natija darhol kerak bo'lmasa.

Umumiy saboq: hech qachon tugamaydigan goroutine deyarli har doim kanalga yozish yoki o'qishning "boshqa tomoni yo'q" holatini ko'rsatadi. Bunday xatoni qidirishda: "bu kanalga har doim kimdir tinglayaptimi?" va "bu goroutine tugashi uchun aynan qanday shart bajarilishi kerak?" degan ikkita savolni bering.

Key Takeaway

Key Takeaway:

Hech qachon tugamaydigan goroutine — odatda kanalga yozish yoki o'qishning "boshqa tomoni" yo'qligini bildiradi: goroutine abadiy kutadi, chunki hech kim uning xabarini qabul qilmaydi. Har bir yaratilgan goroutine uchun "u aniq qachon va qanday tugaydi" savolini bering.

NEXT UP

Writing Up the Root Cause

Case Study: The Goroutine That Never Finishes

Amaliy holat: hech qachon tugamaydigan goroutine

Ikki odamni tasavvur qiling: ular telefon orqali gaplashishga kelishgan, lekin ikkalasi ham "sen birinchi qo'ng'iroq qil" deb, IKKALASI ham kutib turibdi — hech biri birinchi bo'lib qo'ng'iroq qilmaydi. Ular ABADIY shu holatda qolishlari mumkin, chunki har biri boshqasining harakatini kutmoqda. Bu — dasturlashdagi deadlock yoki "hech qachon tugamaydigan kutish"ning aniq tasviri.

Stsenariy: sizning dasturingiz ba'zan "osilib qoladi" — hech qanday xato bermaydi, lekin ham hech narsa qilmaydi, dastur to'xtab qoladi. go tool pprof yoki oddiy kuzatuv orqali, siz goroutine'lar soni VAQT O'TISHI bilan doimiy o'sib borayotganini ko'rasiz — ular ochiladi, lekin hech qachon yopilmaydi.

worker.go
func processInBackground(jobs <-chan Job) {
	results := make(chan Result) // buferlanmagan kanal

	for job := range jobs {
		go func(j Job) {
			result := doWork(j)
			results <- result // bu yerda hech kim tinglamasa, abadiy kutadi
		}(job)
	}
}

Concurrency Fundamentals kursida ko'rgan buferlanmagan (unbuffered) kanal — yuboruvchi va qabul qiluvchi BIR VAQTDA "tayyor" bo'lishini talab qiladi. Bu kodda har bir job uchun yangi goroutine ishga tushiriladi, u ishni bajarib, natijani results kanaliga yubormoqchi bo'ladi — LEKIN hech kim results kanalidan O'QIMAYDI. Har bir goroutine results <- result qatorida ABADIY kutib qoladi.

  • Guessing vs Forming a Hypothesis darsidagi kabi gipoteza: "agar goroutine'lar soni cheksiz o'ssa va hech qachon kamaymasa, demak ular biror joyda BLOKLANIB qolyapti, hech qachon tugamayapti"
  • Har bir yangi job — yangi goroutine yaratadi, lekin processInBackground funksiyasi natijalarni HECH QACHON o'qimaydi — kanal faqat yozish uchun ishlatiladi, o'qish uchun emas
  • Reading a Stack Trace darsidagi kabi: dastur "osilib qolganda" Go'ning SIGQUIT signali (yoki debugger) orqali BARCHA goroutine'larning stack trace'ini olsa, ko'plab goroutine aynan shu results <- result qatorida to'xtab qolganini ko'rasiz

Sabab topildi: results kanaliga yozilgan qiymatlarni hech kim o'qimaydi, shuning uchun har bir yozuvchi goroutine ABADIY bloklanib qoladi — hech qachon tugamaydi, hech qachon xotiradan chiqmaydi. Yechim — yo natijalarni o'qiydigan alohida "yig'uvchi" goroutine qo'shish, yo results kanalini butunlay olib tashlab, agar natija darhol kerak bo'lmasa.

Umumiy saboq: hech qachon tugamaydigan goroutine deyarli har doim kanalga yozish yoki o'qishning "boshqa tomoni yo'q" holatini ko'rsatadi. Bunday xatoni qidirishda: "bu kanalga har doim kimdir tinglayaptimi?" va "bu goroutine tugashi uchun aynan qanday shart bajarilishi kerak?" degan ikkita savolni bering.

Key Takeaway

Key Takeaway:

Hech qachon tugamaydigan goroutine — odatda kanalga yozish yoki o'qishning "boshqa tomoni" yo'qligini bildiradi: goroutine abadiy kutadi, chunki hech kim uning xabarini qabul qilmaydi. Har bir yaratilgan goroutine uchun "u aniq qachon va qanday tugaydi" savolini bering.

NEXT UP

Writing Up the Root Cause