Dalam artikel ini, editor php Xiaoxin akan memperkenalkan isu penting tentang program Go: situasi keluar sebelum kerja goroutine selesai. Dalam bahasa Go, goroutine ialah utas ringan yang boleh melaksanakan tugas secara serentak. Walau bagaimanapun, apabila program kami mungkin keluar sebelum kerja goroutine selesai, kami perlu memahami cara mengendalikan situasi ini untuk memastikan program kami dapat menyelesaikan tugas dengan betul. Dalam kandungan berikut, kami akan meneroka masalah ini dan menyediakan beberapa penyelesaian untuk menyelesaikannya.
Saya menghadapi masalah memahami cara menyekat dan menutup saluran dengan betul. Saya memulakan bilangan pekerja yang sewenang-wenangnya dan saya mendapati bahawa fungsi utama saya sama ada keluar sebelum pekerja selesai atau terhenti disebabkan saluran yang tidak ditutup. Saya memerlukan cara yang lebih baik untuk menghalang pekerja daripada membaca saluran tanpa keluar dari saluran utama, dan kemudian menutup saluran dengan anggun apabila selesai untuk menamatkan gelung. Sebarang percubaan yang saya lakukan berakhir dengan kebuntuan.
Saya telah mencuba beberapa perkara, termasuk menggunakan kumpulan tunggu, tetapi masalah itu berterusan. Saya perasan bahawa dengan menambah time.sleep
program berfungsi seperti yang diharapkan, tetapi mengulasnya menyebabkan tiada kerja dilakukan.
time.sleep(time.duration(10 * time.second))
Berikut ialah contoh yang berfungsi https://go.dev/play/p/qhqnj-ajqbi dengan sleep
dipelihara. Ini ialah kod yang rosak dengan tamat masa tidur diulas.
package main import ( "fmt" "sync" "time" ) // some complicated work func do(num int, ch chan<- int) { time.sleep(time.duration(500 * time.millisecond)) ch <- num } func main() { results := make(chan int) // for some number of required complicated work for i := 0; i < 53; i++ { go do(i, results) } var wg sync.waitgroup // start 3 workers which can process results for i := 0; i < 3; i++ { wg.add(1) go func(id int) { defer wg.done() worker(id, results) }(i) } // handle closing the channel when all workers complete go func() { wg.wait() close(results) }() //time.sleep(time.duration(10 * time.second)) fmt.println("donezo") } // process the results of do() in a meaningful way func worker(id int, ch <-chan int) { fmt.println("starting worker", id) for i := range ch { fmt.println("channel val:", i) } }
Saya juga cuba meletakkan defer wg.done()
移动到 worker()
di dalam func tetapi ia adalah masalah yang sama dan tidak berfungsi tanpa tidur.
// process the results of do() in a meaningful way func worker(wg *sync.WaitGroup, id int, ch <-chan int) { fmt.Println("starting worker", id) defer wg.Done() for i := range ch { fmt.Println("channel val:", i) } }
Adakah saya memilih paradigma yang salah, atau saya hanya menggunakan paradigma yang salah? .
Keluar tanpa memproses semua kandungan dalam saluran
Kebuntuan atau penghantaran pada saluran tertutuprange
saluran dan perkara tidak segerak.
Memandangkan tiada cara praktikal yang jelas dalam penghantar saya untuk menutup saluran (yang disyorkan dalam 99% tutorial saluran), apabila anda mempunyai beberapa pekerja membaca saluran dan pekerja tidak mengetahuinya, dengan goroutine dalam Ia adalah sebenarnya boleh diterima untuk melakukan ini di utama di mana nilai terakhir dibaca.
Penyelesaian
Saya membungkus pekerja itu dalam sync.waitgroup
nya sendiri dan menggunakan worker.wait()
untuk
mencegah
menutup()
saluran secara bebas, iaitu saya menyekat dengan menunggu penulis selesai menggunakan kumpulan tunggu mereka sendiri. close menyediakan penamatan untuk kes gelung julat , kerana apabila nilai lalai saluran dikembalikan, iaitu jenis eof dikembalikan apabila penghujung saluran dicapai, ia akan berakhir menyekat saluran persimpangan sehingga ia ditutup Pandangan saya mengenai ini ialah jika anda tidak tahu berapa banyak nilai yang akan ditolak secara selari, go tidak mempunyai cara untuk mengetahui panjang saluran yang tidak dibuffer kerana ia berada dalam skop, sync.waitgroup
中,并使用 worker.wait()
来阻止程序退出,从而允许工作“完成” ”。当没有更多数据要发送时,我独立地 close()
sehingga anda menutupnya.
akan disekat sehingga selesai.
Contoh operasi yang diselesaikan
workers.wait()
//m.sbmmt.com/link/2bf0ccdbb4d3ebbcb990af74bd78c658
Contoh membaca saluran tertutup //m.sbmmt.com/link/d5397f1497b5cdaad7253fdc92db610b
filling 0 filling 1 filling 2 filling 3 filling 4 filling 5 filling 6 filling 7 filling 8 filling 9 closed empyting 0 empyting 1 empyting 2 empyting 3 empyting 4 empyting 5 empyting 6 empyting 7 empyting 8 empyting 9
Atas ialah kandungan terperinci Pergi program keluar sebelum kerja goroutine selesai. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!