Rumah >pembangunan bahagian belakang >Golang >Mengapa Operasi Saluran Berantai dalam Kes `pilih` Go Menyebabkan Kebuntuan?

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

Linda Hamilton
Linda Hamiltonasal
2024-11-25 05:48:101024semak imbas

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")
}

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

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

select {
    case ch <- <-input1:
    case ch <- <-input2:
}

kami melihat yang pelik tingkah laku:

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

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

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!

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