Menyelesaikan Kebuntuan Goroutine
Apabila bekerja dengan program Golang serentak, anda mungkin mengalami ralat kebuntuan: "ralat maut: semua goroutin sedang tidur - kebuntuan!". Ralat ini berlaku apabila berbilang goroutin sedang menunggu antara satu sama lain untuk melaksanakan tugas, mewujudkan situasi kebuntuan.
Pertimbangkan kod berikut:
<code class="go">func producer(ch chan int, d time.Duration, num int) { for i := 0; i < num; i++ { ch <- i time.Sleep(d) } } func main() { ch := make(chan int) go producer(ch, 100*time.Millisecond, 2) go producer(ch, 200*time.Millisecond, 5) for { fmt.Println(<-ch) } close(ch) }</code>
Kod ini mencipta dua goroutin pengeluar yang menghantar nilai ke saluran yang sama. Goroutine utama secara berterusan menerima nilai daripada saluran dalam gelung yang tidak berkesudahan.
Masalah timbul kerana pengeluar "berumur pendek" dan berhenti menghantar nilai selepas tempoh masa yang terhad, tetapi goroutine utama terus menerima nilai tanpa henti. Ini mewujudkan kebuntuan kerana saluran tidak pernah ditutup untuk memberi isyarat bahawa tiada lagi nilai akan dihantar.
Untuk menyelesaikan kebuntuan ini, kita mesti memastikan saluran ditutup apabila semua pengeluar telah menyelesaikan tugas mereka. Cara yang cekap untuk mencapai matlamat ini ialah menggunakan primitif penyegerakan seperti penyegerakan.WaitGroup.
Berikut ialah versi kod yang diubah suai:
<code class="go">func producer(ch chan int, d time.Duration, num int, wg *sync.WaitGroup) { defer wg.Done() for i := 0; i < num; i++ { ch <- i time.Sleep(d) } } func main() { wg := &sync.WaitGroup{} ch := make(chan int) wg.Add(1) go producer(ch, 100*time.Millisecond, 2, wg) wg.Add(1) go producer(ch, 200*time.Millisecond, 5, wg) go func() { wg.Wait() close(ch) }() for v := range ch { fmt.Println(v) } }</code>
Dalam kod ini, kami menghantar penyegerakan. WaitGroup kepada setiap goroutine pengeluar. Setiap pengeluar menambah kumpulan tunggu sebelum memulakan dan mengurangkannya apabila ia selesai. Goroutin utama menunggu untuk siap semua pengeluar menggunakan wg.Wait(). Setelah semua pengeluar selesai, goroutine utama menutup saluran.
Penyelesaian ini memastikan saluran hanya ditutup selepas semua pengeluar menyelesaikan kerja mereka, mengelakkan situasi kebuntuan.
Atas ialah kandungan terperinci Bagaimana Mencegah Kebuntuan di Golang Apabila Menggunakan Goroutine dan Saluran?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!