Dalam artikel ini, kami akan menganalisis punca di sebalik "kebuntuan!" ralat yang timbul daripada situasi kebuntuan yang melibatkan saluran Go dalam coretan kod berikut:
package main import ( "fmt" "sync" ) func push(c chan int, wg sync.WaitGroup) { for i := 0; i < 5; i++ { c <- i } wg.Done() } func pull(c chan int, wg sync.WaitGroup) { for i := 0; i < 5; i++ { result, ok := <-c fmt.Println(result, ok) } wg.Done() } func main() { var wg sync.WaitGroup wg.Add(2) c := make(chan int) go push(c, wg) go pull(c, wg) wg.Wait() }
Apabila menjalankan kod ini, kami menghadapi ralat berikut:
throw: all goroutines are asleep - deadlock!
Kebuntuan berlaku kerana struktur, seperti penyegerakan.WaitGroup dalam kod ini, dihantar melalui nilai dan bukan melalui rujukan. Ini bermakna apabila kami menghantar WaitGroup ke fungsi kami (tolak dan tarik), kami sebenarnya menghantar salinan WaitGroup dan bukannya objek asal.
Akibatnya, setiap fungsi berfungsi pada salinannya sendiri. WaitGroup, dan apabila mereka memanggil wg.Done(), mereka mengurangkan salinan mereka sendiri. Ini tidak mengemas kini WaitGroup asal, yang merupakan perkara yang ditunggu oleh goroutine utama kami, sekali gus membawa kepada kebuntuan.
Untuk menyelesaikan isu ini, kami perlu lulus penunjuk kepada WaitGroup dan bukannya nilai. Ini akan memastikan bahawa kedua-dua fungsi tolak dan tarik berfungsi pada contoh WaitGroup yang sama, dan panggilan mereka ke wg.Done() akan menjejaskan objek asal.
Berikut ialah versi kod yang diperbetulkan:
package main import ( "fmt" "sync" ) func push(c chan int, wg *sync.WaitGroup) { for i := 0; i < 5; i++ { c <- i } wg.Done() } func pull(c chan int, wg *sync.WaitGroup) { for i := 0; i < 5; i++ { result, ok := <-c fmt.Println(result, ok) } wg.Done() } func main() { var wg sync.WaitGroup wg.Add(2) c := make(chan int) go push(c, &wg) go pull(c, &wg) wg.Wait() }
Dengan membuat perubahan ini, kami kini menghantar penuding kepada WaitGroup kepada fungsi kami, memastikan kedua-duanya bekerja pada objek yang sama dan mengemas kini keadaannya dengan betul. Ini menghapuskan situasi kebuntuan dan membolehkan program kami berjalan tanpa sebarang ralat.
Atas ialah kandungan terperinci Bagaimana untuk Membetulkan Ralat Kebuntuan dalam Saluran Go Apabila Menggunakan sync.WaitGroup?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!