Kebuntuan dalam Go dengan WaitGroup dan Saluran
Dalam Go, kebuntuan berlaku apabila dua atau lebih gorout menunggu selama-lamanya untuk yang lain selesai. Dalam contoh ini, kami akan meneroka isu kebuntuan yang disebabkan oleh penimbal saluran yang tidak mencukupi dan penyegerakan goroutine yang tidak betul menggunakan WaitGroup.
Kod
<code class="go">package main import "fmt" import "sync" func main() { ch := make(chan []int, 4) var m []int var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go func() { defer wg.Done() ch <- m return }() } wg.Wait() for c := range ch { fmt.Printf("c is %v", c) } }</code>
Isunya
Kod cuba menghantar 5 nilai melalui saluran penimbal bersaiz 4. Walau bagaimanapun, apabila saluran penuh, ia menyekat sehingga penerima tersedia. Memandangkan semua goroutine yang menghantar telah selesai, tiada satu pun yang tersedia untuk diterima daripada saluran.
Selain itu, goroutine yang berjulat di atas saluran (untuk c := julat ch) juga kekal disekat selama-lamanya kerana ia menjangkakan lebih banyak nilai untuk tiba di saluran walaupun tiada lagi yang dihantar. Ini mewujudkan kebuntuan di mana kedua-dua penghantar dan penerima sedang menunggu antara satu sama lain.
Penyelesaian 1: Tingkatkan Penampan Saluran dan Tutupnya
Satu penyelesaian untuk mengelakkan kebuntuan adalah dengan meningkatkan saiz penimbal saluran kepada nilai yang lebih besar daripada atau sama dengan bilangan goroutin penghantaran. Selain itu, saluran hendaklah ditutup selepas semua penghantaran selesai, menunjukkan bahawa tiada lagi nilai akan diterima.
<code class="go">ch := make(chan []int, 5) ... wg.Wait() close(ch)</code>
Penyelesaian 2: Lakukan Selesai() dalam Menerima Goroutine
Penyelesaian lain ialah melakukan Done() dalam goroutine penerima dan bukannya dalam fungsi utama. Dengan berbuat demikian, WaitGroup tidak akan dikurangkan sehingga nilai telah diterima dan digunakan oleh goroutine:
<code class="go">func main() { ch := make(chan []int, 4) var m []int var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go func() { ch <- m return }() } go func() { for c := range ch { fmt.Printf("c is %v\n", c) wg.Done() } }() wg.Wait() }</code>
Atas ialah kandungan terperinci Bagaimanakah anda boleh mengelakkan kebuntuan dalam Go apabila menggunakan WaitGroup dan saluran dengan penimbal terhad?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!