Rumah >pembangunan bahagian belakang >Golang >Mengapakah menghantar WaitGroup mengikut nilai dalam saluran Go membawa kepada kebuntuan?

Mengapakah menghantar WaitGroup mengikut nilai dalam saluran Go membawa kepada kebuntuan?

Mary-Kate Olsen
Mary-Kate Olsenasal
2024-10-31 04:59:02463semak imbas

Why does passing a WaitGroup by value in Go channels lead to a deadlock?

Kebuntuan dalam Saluran Go Kerana Lulus Rujukan

Dalam Go, saluran ialah mekanisme komunikasi yang berkuasa, tetapi ia boleh menyebabkan kebuntuan jika tidak digunakan dengan betul. Kebuntuan berlaku apabila dua atau lebih goroutine sedang menunggu antara satu sama lain untuk menyelesaikan operasi, menyebabkan kedua-dua goroutine tidak dapat diteruskan.

Pertimbangkan program Go berikut:


pakej utama

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 anda menjalankan program ini, ia akan panik dengan ralat kebuntuan:

throw: all goroutines are asleep - deadlock!

Masalahnya terletak pada cara WaitGroup dihantar ke goroutine . Dalam Go, struct diluluskan mengikut nilai, yang bermaksud bahawa salinan WaitGroup dihantar ke setiap goroutine. Apabila satu goroutine memanggil Selesai pada salinannya, ia tidak mempunyai kesan pada WaitGroup asal yang dicipta dalam fungsi utama.

Untuk membetulkan kebuntuan, penuding WaitGroup mesti dihantar dan bukannya nilai. Berikut ialah kod yang diperbetulkan:


utama pakej

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 melepasi penunjuk WaitGroup dan bukannya nilai, kedua-dua gorout mempunyai akses kepada yang sama Contoh WaitGroup. Apabila satu goroutine memanggil Selesai, ia mengurangkan kiraan pada WaitGroup asal, membenarkan goroutine yang lain meneruskan.

Atas ialah kandungan terperinci Mengapakah menghantar WaitGroup mengikut nilai dalam saluran Go membawa kepada kebuntuan?. 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