Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimanakah saya boleh mengelakkan kebuntuan apabila menggunakan WaitGroups dan saluran penimbal dalam Go?

Bagaimanakah saya boleh mengelakkan kebuntuan apabila menggunakan WaitGroups dan saluran penimbal dalam Go?

Linda Hamilton
Linda Hamiltonasal
2024-10-26 18:10:02299semak imbas

How can I prevent deadlock when using WaitGroups and buffered channels in Go?

Kebuntuan dalam Go: WaitGroup dan Saluran Buffered

Dalam Go, kebuntuan berlaku apabila gorout serentak menunggu selama-lamanya untuk satu sama lain selesai. Satu punca biasa kebuntuan melibatkan penggunaan WaitGroups dan saluran penimbal.

Contoh Kebuntuan

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 // Sending to a full channel
            return
        }()
    }
    wg.Wait()

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

Kod ini berhasrat untuk menghantar 5 keping kosong ke saluran penimbal dengan kapasiti 4 dan kemudian dibaca dari saluran selepas semua goroutine selesai. Walau bagaimanapun, kod tersebut mengakibatkan ralat kebuntuan.

Punca Kebuntuan

Kebuntuan timbul disebabkan oleh dua isu:

  1. Penimbal Saluran Tidak Mencukupi: Saluran mempunyai kapasiti 4, yang terlalu kecil untuk 5 goroutine yang cuba menghantar data. Apabila saluran menjadi penuh, goroutin berikutnya menunggu untuk menghantar data (baris 15) akan disekat selama-lamanya.
  2. Menyekat Lelaran Saluran: Gelung yang berulang di atas saluran (baris 22-24) menyekat selama-lamanya kerana ia menunggu lebih banyak elemen tiba di saluran. Memandangkan semua goroutine telah selesai menghantar data dan tiada lagi data dijangkakan, lelaran ini tidak akan selesai tanpa bacaan goroutine yang sepadan daripada saluran.

Penyelesaian

Untuk menyelesaikan kebuntuan, buat salah satu daripada pengubahsuaian berikut:

Penyelesaian 1:

Tingkatkan kapasiti saluran kepada 5 (atau lebih) dan tutupnya selepas menghantar semua data :

<code class="go">ch := make(chan []int, 5)
...
wg.Wait()
close(ch)</code>

Penyelesaian 2:

Mulakan goroutine berasingan untuk membaca daripada saluran dan maklumkan goroutine utama apabila semua data telah diterima:

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

Atas ialah kandungan terperinci Bagaimanakah saya boleh mengelakkan kebuntuan apabila menggunakan WaitGroups dan saluran penimbal dalam 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