Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Mengapa Melepasi Nilai Daripada Penunjuk Menyebabkan Kebuntuan dalam Saluran Go?

Mengapa Melepasi Nilai Daripada Penunjuk Menyebabkan Kebuntuan dalam Saluran Go?

Barbara Streisand
Barbara Streisandasal
2024-10-28 21:44:02288semak imbas

Why Does Passing Values Instead of Pointers Cause Deadlock in Go Channels?

Ralat Kebuntuan dalam Saluran Go

Dalam Go, saluran menyediakan cara komunikasi antara goroutine. Walau bagaimanapun, penggunaan saluran yang tidak betul boleh menyebabkan kebuntuan, di mana goroutin disekat selama-lamanya.

Satu punca biasa kebuntuan dengan saluran ialah apabila menghantar jenis nilai dan bukannya penunjuk dalam fungsi goroutine. Ini kerana Go melepasi jenis nilai mengikut nilai, bermakna salinan nilai dibuat.

Pertimbangkan contoh ini:

<code class="go">import (
    "fmt"
    "sync"
)

func push(c chan int, wg sync.WaitGroup) {
    for i := 0; i < 5; i++ {
        c <- i
    }
    wg.Done()
}

func pull(c chan int, wg sync.WaitGroup) {
    for i := 0; i < 5; i++ {
        result, ok := <-c
        fmt.Println(result, ok)
    }
    wg.Done()
}

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

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

    wg.Wait()
}</code>

Menjalankan program mengakibatkan ralat jalan buntu:

    0 true
    1 true
    2 true
    3 true
    4 true
    throw: all goroutines are asleep - deadlock!

Kebuntuan berlaku kerana WaitGroup dihantar ke fungsi tolak dan tarik sebagai nilai. Apabila WaitGroup dikemas kini dalam salah satu goroutine, perubahan tidak ditunjukkan dalam goroutine yang lain kerana ia mempunyai salinan nilai.

Untuk menyelesaikan kebuntuan, kita perlu menghantar WaitGroup sebagai penunjuk, yang memastikan kedua-dua goroutine beroperasi pada contoh WaitGroup yang sama.

Berikut ialah versi kod yang diperbetulkan:

<code class="go">import (
    "fmt"
    "sync"
)

func push(c chan int, wg *sync.WaitGroup) {
    for i := 0; i < 5; i++ {
        c <- i
    }
    wg.Done()
}

func pull(c chan int, wg *sync.WaitGroup) {
    for i := 0; i < 5; i++ {
        result, ok := <-c
        fmt.Println(result, ok)
    }
    wg.Done()
}

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

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

    wg.Wait()
}</code>

Atas ialah kandungan terperinci Mengapa Melepasi Nilai Daripada Penunjuk Menyebabkan Kebuntuan dalam Saluran Go?. 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