Mengapa Operasi Saluran Berantai dalam Kes `pilih` Go Menyebabkan Kebuntuan?

Linda Hamilton
Lepaskan: 2024-11-25 05:48:10
asal
957 orang telah melayarinya

Why Do Chained Channel Operations in Go's `select` Case Cause Deadlocks?

Operasi Saluran Berantai dalam Kes Pilihan Tunggal: Menyahkod Gelagat

Dalam usaha mereka bentuk program serentak dan tak segerak, binaan pilihan Go menyediakan alat yang berkuasa untuk memultiplekskan saluran. Walau bagaimanapun, seseorang sering menghadapi hasil yang tidak dijangka apabila menggabungkan berbilang operasi dalam satu kes terpilih.

Pertimbangkan senario berikut: dua saluran, A dan B, menghantar mesej pada selang masa yang berbeza (10 milisaat untuk A dan 1 saat untuk B). Kami menggunakan pilih untuk mendengar kedua-dua saluran dan memajukan nilai yang diterima ke saluran peminat masuk.

func main() {
    ch := fanIn(talk("A", 10), talk("B", 1000))

    for i := 0; i < 10; i++ {
        fmt.Printf("%q\n", <-ch)
    }
    fmt.Printf("Done\n")
}
Salin selepas log masuk

Hasil yang dijangkakan ialah:

"A 0"
"B 0"
"A 1"
"A 2"
"A 3"
"A 4"
"B 1"
"B 2"
"B 3"
"B 4"
Done
Salin selepas log masuk

Walau bagaimanapun, apabila kami mengubah suai pilihan kes untuk menggunakan operasi saluran berantai:

select {
    case ch <- <-input1:
    case ch <- <-input2:
}
Salin selepas log masuk

kami melihat yang pelik tingkah laku:

"B 0"
"A 1"
"B 2"
"A 3"
"A 4"
fatal error: all goroutines are asleep - deadlock!
Salin selepas log masuk

Di Sebalik Tabir

Kunci untuk memahami tingkah laku ini terletak pada sifat tidak menyekat operasi saluran dalam kes terpilih. Dalam kes pilihan biasa, hanya satu operasi saluran (sama ada baca atau tulis) tidak boleh disekat.

Apabila kami menggunakan operasi saluran berantai, kami cuba dengan berkesan berbilang operasi saluran dalam satu kes. Operasi pertama sentiasa menyekat, manakala operasi seterusnya tidak menyekat.

Dalam kod diubah suai kami, operasi pertama menyekat untuk menerima nilai daripada input1. Selepas menerima nilai, ia cuba menulisnya ke saluran ch tanpa sekatan. Walau bagaimanapun, jika penerima saluran ch tidak bersedia untuk menerima nilai, operasi tulis akan gagal.

Tindak Balas Rantaian

Operasi tulis yang gagal tidak hentikan kes pilih. Sebaliknya, ia beralih kepada kes kedua, yang kini merupakan satu-satunya kes yang berdaya maju. Ini mengakibatkan senario jalan buntu yang berpotensi.

Dari masa ke masa, berbilang nilai daripada kedua-dua saluran diterima tetapi tidak dimajukan ke saluran kipas masuk kerana penulisan yang gagal. Akibatnya, saluran kipas masuk akhirnya menjadi kosong, membawa kepada kebuntuan kerana tiada lagi nilai boleh diterima.

Menyelesaikan Isu

Untuk mengelakkan isu ini, ia adalah penting untuk memastikan bahawa operasi saluran dalam kes terpilih dilaksanakan secara bersiri. Ini boleh dicapai dengan menggunakan pembolehubah sementara untuk menyimpan nilai yang diterima dan kemudian melaksanakan operasi tulis sebagai pernyataan berasingan di luar kes pilihan.

var msg string
select {
    case msg = <-input1:
    case msg = <-input2:
}

ch <- msg
Salin selepas log masuk

Atas ialah kandungan terperinci Mengapa Operasi Saluran Berantai dalam Kes `pilih` Go Menyebabkan 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