Amalan Terbaik untuk Menggunakan penyegerakan.WaitGroup dengan Fungsi Luaran
Dalam menangani konkurensi dalam Go, adalah penting untuk menggunakan penyegerakan dengan berkesan.WaitGroup. Artikel ini menangani isu biasa yang timbul semasa menghantar kumpulan tunggu sebagai hujah kepada fungsi luaran.
Masalah:
Pertimbangkan kod berikut:
<code class="go">package main import ( "fmt" "sync" ) func main() { ch := make(chan int) var wg sync.WaitGroup wg.Add(2) go Print(ch, wg) // go func(){ for i := 1; i <= 11; i++ { ch <- i } close(ch) defer wg.Done() }() wg.Wait() //deadlock here } // Print prints all numbers sent on the channel. // The function returns when the channel is closed. func Print(ch <-chan int, wg sync.WaitGroup) { for n := range ch { // reads from channel until it's closed fmt.Println(n) } defer wg.Done() }</code>
Dalam kod ini, kebuntuan berlaku pada baris yang ditentukan, menyebabkan atur cara mencetak hanya dari 1 hingga 10 dan bukannya mencapai 11. Ralat berpunca daripada menghantar salinan penyegerakan.WaitGroup kepada kaedah Cetak, yang menghalang panggilan yang dijangkakan kepada kaedah Selesai.
Penyelesaian 1:
Untuk menyelesaikan isu ini, alihkan penunjuk kepada kumpulan tunggu:
<code class="go">package main import ( "fmt" "sync" ) func main() { ch := make(chan int) var wg sync.WaitGroup wg.Add(2) go Print(ch, &wg) go func() { for i := 1; i <= 11; i++ { ch <- i } close(ch) defer wg.Done() }() wg.Wait() //deadlock here } func Print(ch <-chan int, wg *sync.WaitGroup) { for n := range ch { // reads from channel until it's closed fmt.Println(n) } defer wg.Done() }</code>
Meluluskan alamat wg memastikan kaedah Cetak memanggil kaedah Selesai pada kumpulan tunggu yang menunggu dalam fungsi utama.
Penyelesaian 2: Kaedah Cetakan Ringkas
Sebagai alternatif, kaedah Cetak boleh dipermudahkan dengan mengalih keluar argumen WaitGroup, kerana ia tidak memerlukan pengetahuan tentang sebarang operasi menunggu:
<code class="go">package main import ( "fmt" ) func main() { ch := make(chan int) go func() { for i := 1; i <= 11; i++ { ch <- i } close(ch) }() for n := range ch { // reads from channel until it's closed fmt.Println(n) } } </code>
Dalam senario ini, goroutine utama menerima terus saluran dan mencetak nilainya tanpa melibatkan kumpulan menunggu. Pendekatan ini mengekalkan kefungsian yang diingini dan menghapuskan keperluan untuk pengurusan WaitGroup dalam kaedah Cetak.
Kesimpulan:
Apabila menghantar penyegerakan.WaitGroup sebagai hujah kepada fungsi luaran, adalah penting untuk memastikan bahawa fungsi menerima rujukan yang betul kepada kumpulan tunggu yang sedang menunggu. Memfaktorkan semula fungsi untuk mengendalikan kumpulan menunggu secara terus atau menghantar penunjuk kepada kumpulan menunggu dengan berkesan boleh menghalang ralat kebuntuan dan memastikan kawalan serentak yang betul.
Atas ialah kandungan terperinci Bagaimana untuk Mengelakkan Kebuntuan Apabila Menggunakan sync.WaitGroup dengan Fungsi Luaran dalam Go?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!