Rumah > pembangunan bahagian belakang > Golang > Bagaimanakah Operasi Saluran Berantai dalam Penyata `select` Go Boleh Membawa kepada Kebuntuan dan Kehilangan Data?

Bagaimanakah Operasi Saluran Berantai dalam Penyata `select` Go Boleh Membawa kepada Kebuntuan dan Kehilangan Data?

Linda Hamilton
Lepaskan: 2024-12-01 22:04:13
asal
738 orang telah melayarinya

How Can Chained Channel Operations in Go's `select` Statement Lead to Deadlocks and Data Loss?

Merantai Operasi Saluran dalam Kes Pilihan Tunggal: Menganalisis Kemungkinan Perangkap

Dalam Go, pernyataan pilih menyediakan cara yang mudah untuk memultiplekskan berbilang saluran. Pertimbangkan senario berikut: kami mempunyai dua saluran, A dan B, menghantar mesej pada selang masa yang berbeza. Kami ingin mencipta saluran peminat yang menerima mesej daripada A dan B.

Kod di bawah menunjukkan perkara ini:

func fanIn(input1, input2 <-chan string) <-chan string {
    ch := make(chan string)
    go func() {
        for {
            select {
                case t := <-input1:
                    ch <- t
                case t := <-input2:
                    ch <- t
            }
        }
    }()

    return ch
}
Salin selepas log masuk

Apabila kami menjalankan kod ini, kami menjangkakan untuk menerima mesej daripada kedua-dua saluran secara bersilang. Walau bagaimanapun, jika kami mengubah suai penyataan kes pilih seperti berikut, kami menghadapi gelagat yang tidak dijangka:

func fanIn(input1, input2 <-chan string) <-chan string {
    ch := make(chan string)
    go func() {
        for {
            select {
                case ch <- <-input1:
                case ch <- <-input2:
            }
        }
    }()

    return ch
}
Salin selepas log masuk

Dalam kes ini, kami menerima beberapa mesej dengan betul, tetapi kemudian kami mengalami penurunan nilai dan akhirnya menemui jalan buntu. Sebab bagi tingkah laku ini terletak pada kerja asas pilih.

Dalam pilih, hanya satu operasi baca atau tulis saluran tidak menyekat. Semua operasi lain berkelakuan normal. Dalam kod yang diubah suai, kedua-dua kes mengandungi penulisan saluran, yang tidak disekat. Ini membawa kepada situasi di mana mesej daripada saluran input beratur, tetapi saluran kipas masuk hanya boleh menggunakan satu demi satu.

Akibatnya, mesej boleh digugurkan dan kebuntuan berlaku apabila kipas masuk saluran tidak mempunyai penulis dan pembaca sedang menunggu lebih banyak nilai.

Untuk mengelakkan isu ini, adalah penting untuk memahami bahawa dalam pernyataan pilihan, hanya satu operasi harus tidak menyekat. Jika anda perlu melakukan operasi berbilang saluran dalam satu kes pilihan, pertimbangkan untuk menggunakan fungsi pembantu pilih yang tidak menyekat seperti ini:

func nonBlockingSelect(cases []reflect.SelectCase) (chosen int, recv interface{}, ok bool) {
    for i, c := range cases {
        if c.Dir == reflect.SelectSend && c.Chan == nil {
            continue
        }
        v, ok := reflect.Select(cases)
        return v.Index, v.Elem().Interface(), ok
    }

    return -1, nil, false
}
Salin selepas log masuk

Kemudian, fungsi kipas masuk yang diubah suai boleh ditulis semula sebagai:

func fanIn(input1, input2 <-chan string) <-chan string {
    ch := make(chan string)
    go func() {
        for {
            select {
                case c1 := <-input1:
                    nonBlockingSelect([]reflect.SelectCase{
                        {Dir: reflect.SelectSend, Chan: reflect.ValueOf(ch), Send: reflect.ValueOf(c1)},
                    })
                case c2 := <-input2:
                    nonBlockingSelect([]reflect.SelectCase{
                        {Dir: reflect.SelectSend, Chan: reflect.ValueOf(ch), Send: reflect.ValueOf(c2)},
                    })
            }
        }
    }()

    return ch
}
Salin selepas log masuk

Menggunakan pembantu pilih yang tidak menyekat memastikan bahawa hanya satu operasi saluran tidak menyekat, menghalang isu penurunan nilai dan kebuntuan.

Atas ialah kandungan terperinci Bagaimanakah Operasi Saluran Berantai dalam Penyata `select` Go Boleh Membawa kepada Kebuntuan dan Kehilangan Data?. 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