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

Linda Hamilton
Lepaskan: 2024-10-26 18:10:02
asal
308 orang telah melayarinya

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>
Salin selepas log masuk

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>
Salin selepas log masuk

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>
Salin selepas log masuk

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!

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
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!