Kebuntuan dalam Go: "semua rutin pergi sedang tidur"
Apabila menjalankan kod yang disediakan, jalan buntu berlaku disebabkan model pelaksanaan tak segeraknya menggunakan goroutine. Isu timbul apabila fungsi UnloadTrucks dipanggil sebelum sebarang trak dihantar ke saluran. Ini membawa kepada saluran kekal kosong, menyebabkan gorout penghantar disekat pada baris ch <- tr. Memandangkan goroutine penghantar sedang menunggu untuk menghantar trak, mereka tidak boleh menutup saluran, dan fungsi UnloadTrucks, yang menunggu untuk menerima trak, tersekat selama-lamanya.
Penyelesaian: Menggunakan WaitGroup untuk Menutup Saluran
Untuk menyelesaikan kebuntuan, kami boleh menutup saluran ch selepas semua goroutine selesai menghantar trak. Ini boleh dicapai dengan memperkenalkan WaitGroup, primitif penyegerakan yang menjejaki bilangan goroutin yang belum selesai:
go func() { wg.Wait() close(ch) }()
Groutine ini menunggu sehingga semua goroutine lain menyelesaikan tugas mereka (diisyaratkan oleh panggilan Tunggu() sebelum menutup saluran. Dengan berbuat demikian, fungsi UnloadTrucks dapat keluar dengan anggun apabila semua trak telah dihantar.
Kod Semakan:
package main import ( "fmt" "sync" "time" ) type Item struct { name string } type Truck struct { Cargo []Item name string } func UnloadTrucks(c chan Truck) { for t := range c { fmt.Printf("%s has %d items in cargo: %s\n", t.name, len(t.Cargo), t.Cargo[0].name) } } func main() { trucks := make([]Truck, 2) ch := make(chan Truck) var wg sync.WaitGroup for i, _ := range trucks { trucks[i].name = fmt.Sprintf("Truck %d", i+1) fmt.Printf("Building %s\n", trucks[i].name) } for t := range trucks { go func(tr Truck) { itm := Item{} itm.name = "Groceries" fmt.Printf("Loading %s\n", tr.name) tr.Cargo = append(tr.Cargo, itm) ch <- tr wg.Done() }(trucks[t]) wg.Add(1) } time.Sleep(50 * time.Millisecond) fmt.Println("Unloading Trucks") UnloadTrucks(ch) fmt.Println("Done") }
Dengan kod yang diubah suai ini, kebuntuan dihapuskan kerana fungsi UnloadTrucks dijamin menerima semua trak sebelum saluran ditutup. Ini memastikan semua gorout menyelesaikan tugas mereka dengan betul dan program berjalan tanpa sebarang gangguan yang tidak dijangka.
Atas ialah kandungan terperinci Bagaimana untuk Menyelesaikan Kebuntuan Pergi yang Disebabkan oleh Operasi Asynchronous dan Saluran Kosong?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!