editor php Baicao akan menjawab soalan biasa dalam artikel ini: "Apakah punca kebuntuan dalam kod Go menggunakan WaitGroups dan Saluran Penimbalan?" Walau bagaimanapun, kadangkala anda mungkin menghadapi situasi kebuntuan dalam kod yang menggunakannya. Artikel ini akan menyelidiki punca kebuntuan dan menyediakan penyelesaian untuk membantu pembaca mengelakkan masalah ini. Sama ada anda seorang pemula atau pembangun Go yang berpengalaman, artikel ini akan memberikan anda maklumat yang berharga.
Kumpulan menunggu, saluran penampan dan kebuntuan
Kod saya ini menyebabkan kebuntuan, tetapi saya tidak pasti mengapa. Saya telah mencuba menggunakan mutex di beberapa tempat yang berbeza, menutup saluran di dalam dan di luar rutin pergi yang berasingan, tetapi masih keputusan yang sama.
Saya cuba menghantar data melalui satu saluran (inputchan) dan kemudian membaca data dari saluran lain (outputchan)
package main import ( "fmt" "sync" ) func listStuff(wg *sync.WaitGroup, workerID int, inputChan chan int, outputChan chan int) { defer wg.Done() for i := range inputChan { fmt.Println("sending ", i) outputChan <- i } } func List(workers int) ([]int, error) { _output := make([]int, 0) inputChan := make(chan int, 1000) outputChan := make(chan int, 1000) var wg sync.WaitGroup wg.Add(workers) fmt.Printf("+++ Spinning up %v workers\n", workers) for i := 0; i < workers; i++ { go listStuff(&wg, i, inputChan, outputChan) } for i := 0; i < 3000; i++ { inputChan <- i } done := make(chan struct{}) go func() { close(done) close(inputChan) close(outputChan) wg.Wait() }() for o := range outputChan { fmt.Println("reading from channel...") _output = append(_output, o) } <-done fmt.Printf("+++ output len: %v\n", len(_output)) return _output, nil } func main() { List(5) }
Kod dalam fungsi utama adalah berterusan, Pertamacuba tulis nilai 3k ke inputchan
inputchan
然后将从 outputchan
Kemudian
outputchan</ kod>. <p>
</p>Kod anda disekat pada langkah pertama: <ul>
<li>
<code>inputchan
之前,outputchan
不会流失任何内容,因此工作人员最终会在第一个 1k 值之后卡在 outputchan <- i
Berjaya menghantar nilai 3k kepada inputchan
中消耗资源,main
将在大约 2k 个值之后卡在 inputchan <- i
Setelah kakitangan berhenti dari
inputchan <- i
) 和最终消费者 (for o := range outputchan {
Salah satu cara untuk menyelesaikan masalah ini ialah dengan meminta pengeluar (
Anda boleh menyimpan salah seorang pelakon ini dalam goroutine utama dan memutarkan pelakon baharu untuk pelakon lain. Contohnya:
go func(inputchan chan<- int){ for i := 0; i < 3000; i++ { inputchan <- i } close(inputchan) }(inputchan) done := make(chan struct{}) go func() { close(done) // close(inputchan) // i chose to close inputchan above, don't close it twice close(outputchan) wg.wait() }() ...
done
的操作顺序很重要;通道 done
和 outputchan
只能在 wg.done()
Nota tambahan: isyarat sekeliling untuk mengarahkan semua kakitangan menutup apabila selesai
// it is best to close inputChan next to the code that controls // when its input is complete. close(inputChan) // If you had several producers writing to the same channel, you // would probably have to add a separate waitgroup to handle closing, // much like you did for your workers go func() { wg.Wait() // the two following actions must happen *after* workers have // completed close(done) close(outputChan) }()
Atas ialah kandungan terperinci Apakah punca kebuntuan dalam kod Go menggunakan WaitGroups dan Saluran Buffer?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!