Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimana Mencegah Kebuntuan di Golang Apabila Menggunakan Goroutine dan Saluran?

Bagaimana Mencegah Kebuntuan di Golang Apabila Menggunakan Goroutine dan Saluran?

Susan Sarandon
Susan Sarandonasal
2024-10-27 06:48:29393semak imbas

How to Prevent Deadlock in Golang When Using Goroutines and Channels?

Menyelesaikan Kebuntuan Goroutine

Apabila bekerja dengan program Golang serentak, anda mungkin mengalami ralat kebuntuan: "ralat maut: semua goroutin sedang tidur - kebuntuan!". Ralat ini berlaku apabila berbilang goroutin sedang menunggu antara satu sama lain untuk melaksanakan tugas, mewujudkan situasi kebuntuan.

Pertimbangkan kod berikut:

<code class="go">func producer(ch chan int, d time.Duration, num int) {
    for i := 0; i < num; i++ {
        ch <- i
        time.Sleep(d)
    }
}

func main() {
    ch := make(chan int)

    go producer(ch, 100*time.Millisecond, 2)
    go producer(ch, 200*time.Millisecond, 5)

    for {
        fmt.Println(<-ch)    
    }

    close(ch)
}</code>

Kod ini mencipta dua goroutin pengeluar yang menghantar nilai ke saluran yang sama. Goroutine utama secara berterusan menerima nilai daripada saluran dalam gelung yang tidak berkesudahan.

Masalah timbul kerana pengeluar "berumur pendek" dan berhenti menghantar nilai selepas tempoh masa yang terhad, tetapi goroutine utama terus menerima nilai tanpa henti. Ini mewujudkan kebuntuan kerana saluran tidak pernah ditutup untuk memberi isyarat bahawa tiada lagi nilai akan dihantar.

Untuk menyelesaikan kebuntuan ini, kita mesti memastikan saluran ditutup apabila semua pengeluar telah menyelesaikan tugas mereka. Cara yang cekap untuk mencapai matlamat ini ialah menggunakan primitif penyegerakan seperti penyegerakan.WaitGroup.

Berikut ialah versi kod yang diubah suai:

<code class="go">func producer(ch chan int, d time.Duration, num int, wg *sync.WaitGroup) {
    defer wg.Done()

    for i := 0; i < num; i++ {
        ch <- i
        time.Sleep(d)
    }
}

func main() {
    wg := &sync.WaitGroup{}
    ch := make(chan int)

    wg.Add(1)
    go producer(ch, 100*time.Millisecond, 2, wg)
    wg.Add(1)
    go producer(ch, 200*time.Millisecond, 5, wg)

    go func() {
        wg.Wait()
        close(ch)
    }()

    for v := range ch {
        fmt.Println(v)
    }
}</code>

Dalam kod ini, kami menghantar penyegerakan. WaitGroup kepada setiap goroutine pengeluar. Setiap pengeluar menambah kumpulan tunggu sebelum memulakan dan mengurangkannya apabila ia selesai. Goroutin utama menunggu untuk siap semua pengeluar menggunakan wg.Wait(). Setelah semua pengeluar selesai, goroutine utama menutup saluran.

Penyelesaian ini memastikan saluran hanya ditutup selepas semua pengeluar menyelesaikan kerja mereka, mengelakkan situasi kebuntuan.

Atas ialah kandungan terperinci Bagaimana Mencegah Kebuntuan di Golang Apabila Menggunakan Goroutine dan Saluran?. 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