Rumah >pembangunan bahagian belakang >Golang >Bagaimana untuk Membetulkan Ralat Kebuntuan dalam Saluran Go Apabila Menggunakan sync.WaitGroup?

Bagaimana untuk Membetulkan Ralat Kebuntuan dalam Saluran Go Apabila Menggunakan sync.WaitGroup?

Patricia Arquette
Patricia Arquetteasal
2024-10-29 02:36:02470semak imbas

How to Fix Deadlock Errors in Go Channels When Using sync.WaitGroup?

Memahami Ralat Kebuntuan dalam Saluran Go

Dalam artikel ini, kami akan menganalisis punca di sebalik "kebuntuan!" ralat yang timbul daripada situasi kebuntuan yang melibatkan saluran Go dalam coretan kod berikut:

package main

import (
    "fmt"
    "sync"
)

func push(c chan int, wg sync.WaitGroup) {
    for i := 0; i < 5; i++ {
        c <- i
    }
    wg.Done()
}

func pull(c chan int, wg sync.WaitGroup) {
    for i := 0; i < 5; i++ {
        result, ok := <-c
        fmt.Println(result, ok)
    }
    wg.Done()
}

func main() {
    var wg sync.WaitGroup
    wg.Add(2)
    c := make(chan int)

    go push(c, wg)
    go pull(c, wg)

    wg.Wait()
}

Apabila menjalankan kod ini, kami menghadapi ralat berikut:

throw: all goroutines are asleep - deadlock!

Memahami Deadlock

Kebuntuan berlaku kerana struktur, seperti penyegerakan.WaitGroup dalam kod ini, dihantar melalui nilai dan bukan melalui rujukan. Ini bermakna apabila kami menghantar WaitGroup ke fungsi kami (tolak dan tarik), kami sebenarnya menghantar salinan WaitGroup dan bukannya objek asal.

Akibatnya, setiap fungsi berfungsi pada salinannya sendiri. WaitGroup, dan apabila mereka memanggil wg.Done(), mereka mengurangkan salinan mereka sendiri. Ini tidak mengemas kini WaitGroup asal, yang merupakan perkara yang ditunggu oleh goroutine utama kami, sekali gus membawa kepada kebuntuan.

Memperbaiki Kebuntuan

Untuk menyelesaikan isu ini, kami perlu lulus penunjuk kepada WaitGroup dan bukannya nilai. Ini akan memastikan bahawa kedua-dua fungsi tolak dan tarik berfungsi pada contoh WaitGroup yang sama, dan panggilan mereka ke wg.Done() akan menjejaskan objek asal.

Berikut ialah versi kod yang diperbetulkan:

package main

import (
    "fmt"
    "sync"
)

func push(c chan int, wg *sync.WaitGroup) {
    for i := 0; i < 5; i++ {
        c <- i
    }
    wg.Done()
}

func pull(c chan int, wg *sync.WaitGroup) {
    for i := 0; i < 5; i++ {
        result, ok := <-c
        fmt.Println(result, ok)
    }
    wg.Done()
}

func main() {
    var wg sync.WaitGroup
    wg.Add(2)
    c := make(chan int)

    go push(c, &wg)
    go pull(c, &wg)

    wg.Wait()
}

Dengan membuat perubahan ini, kami kini menghantar penuding kepada WaitGroup kepada fungsi kami, memastikan kedua-duanya bekerja pada objek yang sama dan mengemas kini keadaannya dengan betul. Ini menghapuskan situasi kebuntuan dan membolehkan program kami berjalan tanpa sebarang ralat.

Atas ialah kandungan terperinci Bagaimana untuk Membetulkan Ralat Kebuntuan dalam Saluran Go Apabila Menggunakan sync.WaitGroup?. 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