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

Mary-Kate Olsen
Lepaskan: 2024-10-31 04:59:02
asal
373 orang telah melayarinya

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"
Salin selepas log masuk
Salin selepas log masuk

)

func push(c chan int, wg sync.WaitGroup) {

for i := 0; i < 5; i++ {
    c <- i
}
wg.Done()
Salin selepas log masuk
Salin selepas log masuk

}

func pull(c chan int, wg sync.WaitGroup) {

for i := 0; i < 5; i++ {
    result, ok := <-c
    fmt.Println(result, ok)
}
wg.Done()
Salin selepas log masuk
Salin selepas log masuk

}

func main() {

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

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

wg.Wait()
Salin selepas log masuk

}

Apabila anda menjalankan program ini, ia akan panik dengan ralat kebuntuan:

throw: all goroutines are asleep - deadlock!
Salin selepas log masuk

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"
Salin selepas log masuk
Salin selepas log masuk

)

func push(c chan int , wg *sync.WaitGroup) {

for i := 0; i < 5; i++ {
    c <- i
}
wg.Done()
Salin selepas log masuk
Salin selepas log masuk

}

func pull(c chan int, wg *sync.WaitGroup) {

for i := 0; i < 5; i++ {
    result, ok := <-c
    fmt.Println(result, ok)
}
wg.Done()
Salin selepas log masuk
Salin selepas log masuk

}

func main() {

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

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

wg.Wait()
Salin selepas log masuk

}

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!

sumber:php.cn
Kenyataan Laman Web ini
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
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!