Rumah >pembangunan bahagian belakang >Golang >Bagaimana untuk Mengelakkan Kebuntuan Apabila Menggunakan sync.WaitGroup dengan Fungsi Luaran dalam Go?

Bagaimana untuk Mengelakkan Kebuntuan Apabila Menggunakan sync.WaitGroup dengan Fungsi Luaran dalam Go?

Mary-Kate Olsen
Mary-Kate Olsenasal
2024-11-05 22:03:02965semak imbas

How to Avoid Deadlocks When Using sync.WaitGroup with External Functions in Go?

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!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn