Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Mengapakah kod Go yang disediakan dengan WaitGroup dan saluran penimbal mengakibatkan kebuntuan?

Mengapakah kod Go yang disediakan dengan WaitGroup dan saluran penimbal mengakibatkan kebuntuan?

Barbara Streisand
Barbara Streisandasal
2024-10-26 22:08:02680semak imbas

Why does the provided Go code with WaitGroup and buffered channel result in a deadlock?

Kebuntuan dalam Go dengan WaitGroup dan Saluran Penimbalan

Dalam Go, jalan buntu berlaku apabila berbilang gorout sedang menunggu satu sama lain untuk selesai, mengakibatkan dalam kebuntuan. Keadaan ini boleh timbul apabila menggunakan saluran penimbal dan WaitGroups secara tidak betul.

Pertimbangkan kod berikut:

<code class="go">package main

import "fmt"
import "sync"

func main() {
    ch := make(chan []int, 4)
    var m []int

    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            ch <- m
            return
        }()
    }
    wg.Wait()

    for c := range ch {
        fmt.Printf("c is %v", c)
    }
}</code>

Kod ini dijangka akan mencipta saluran dengan saiz penimbal 4 dan memulakan 5 gorouti , masing-masing menghantar kepingan kosong ke saluran. Goroutine utama menunggu sehingga semua goroutine selesai dan kemudian berjulat di atas saluran.

Walau bagaimanapun, kod ini akan mengakibatkan kebuntuan. Mengapa?

Punca Kebuntuan:

Dua masalah wujud dalam kod:

  1. Kapasiti Saluran: Saluran mempunyai kapasiti sebanyak 4, yang bermaksud ia boleh memuatkan sehingga 4 elemen. Walau bagaimanapun, terdapat 5 goroutine cuba dihantar ke saluran, mengakibatkan situasi di mana goroutine terakhir akan menyekat menunggu slot untuk dibebaskan.
  2. Menutup Saluran: Gelung julat ch terus menunggu elemen untuk memasuki saluran. Memandangkan tiada lagi goroutine yang tinggal untuk menulis ke saluran, gelung akan menunggu selama-lamanya.

Penyelesaian:

  1. Tingkatkan Kapasiti Saluran: Dengan meningkatkan kapasiti saluran kepada 5, slot yang mencukupi akan tersedia untuk semua gorout menghantar nilai mereka tanpa menyekat. Selain itu, menutup saluran selepas goroutine selesai menulis akan memberi isyarat kepada gelung julat bahawa tiada lagi elemen akan datang, menghalangnya daripada menunggu selama-lamanya.

    <code class="go">ch := make(chan []int, 5)
    ...
    wg.Wait()
    close(ch)</code>
  2. Gunakan Selesai () dalam Gelung: Daripada menutup saluran, seseorang boleh menggunakan kaedah Done() WaitGroup untuk memberi isyarat apabila goroutine terakhir telah selesai. Dengan memanggil Done() dalam gelung julat, goroutine utama akan dimaklumkan apabila saluran kosong dan gelung boleh keluar.

    <code class="go">go func() {
        for c := range ch {
            fmt.Printf("c is %v\n", c)
            wg.Done()
        }
    }()
    wg.Wait()</code>

Penyelesaian ini menyelesaikan kebuntuan dengan memastikan bahawa saluran mempunyai kapasiti yang mencukupi dan gelung julat keluar apabila tiada lagi elemen untuk dibaca daripada saluran.

Atas ialah kandungan terperinci Mengapakah kod Go yang disediakan dengan WaitGroup dan saluran penimbal mengakibatkan 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