Rumah > pembangunan bahagian belakang > Golang > Mengapa Menggunakan Saluran Tanpa Penimbalan dalam Pergi Membawa kepada Kebuntuan?

Mengapa Menggunakan Saluran Tanpa Penimbalan dalam Pergi Membawa kepada Kebuntuan?

Mary-Kate Olsen
Lepaskan: 2024-12-18 16:55:10
asal
363 orang telah melayarinya

Why Does Using Unbuffered Channels in Go Lead to Deadlock?

Kebuntuan dalam Model Concurrency of Go: Menggunakan Saluran Tanpa Penimbalan

Dalam model concurrency Go, saluran ialah mekanisme asas untuk komunikasi antara goroutine . Walau bagaimanapun, tingkah laku saluran boleh berbeza-beza bergantung pada saiz penimbalnya. Di sini, kami menyelidiki senario kebuntuan yang timbul apabila menggunakan saluran tidak buffer.

Masalahnya

Pertimbangkan coretan kod Go berikut:

package main

import "fmt"

func main() {
    c := make(chan int)    
    c <- 1   
    fmt.Println(<-c)
}
Salin selepas log masuk

Apabila dilaksanakan, kod ini menghasilkan a kebuntuan:

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()
    /path/to/file:8 +0x52
exit status 2
Salin selepas log masuk

Penjelasan

Kebuntuan berlaku kerana penggunaan saluran yang tidak dibuffer. Saluran yang tidak dibuffer, seperti yang dinyatakan dalam dokumentasi, memerlukan kehadiran penerima sebelum nilai boleh dihantar. Dalam kes ini, saluran dimulakan sebagai tidak penimbal secara lalai (dengan saiz penimbal 0).

Apabila baris c <- 1 dilaksanakan, goroutine cuba menghantar nilai 1 ke saluran. Walau bagaimanapun, memandangkan saluran tidak mempunyai penimbal, ia menunggu penerima untuk mendapatkan semula nilai sebelum meneruskan.

Serentak, pernyataan fmt.Println(<-c) cuba menerima nilai daripada saluran. Walau bagaimanapun, memandangkan tiada nilai dihantar lagi (kerana goroutine sedang menunggu penerima), operasi terima akan terhalang.

Ini mengakibatkan jalan buntu, kerana kedua-dua goroutine sedang menunggu yang lain untuk menyelesaikan operasi. boleh melakukan tanpa yang lain.

Penyelesaian

Untuk menyelesaikan kebuntuan, seseorang mesti memperkenalkan penerima untuk saluran. Dengan mencipta goroutine berasingan untuk mengendalikan penerimaan nilai yang dihantar, kebuntuan boleh dihapuskan. Kod yang diubah suai di bawah menunjukkan penyelesaian ini:

package main

import "fmt"

func main() {
    c := make(chan int)    
    go func() {
        fmt.Println("received:", <-c)
    }()
    c <- 1   
}
Salin selepas log masuk

Atas ialah kandungan terperinci Mengapa Menggunakan Saluran Tanpa Penimbalan dalam Pergi 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