Bagaimanakah Kebuntuan Boleh Berlaku Apabila Menggunakan WaitGroups dan Saluran Penimbalan dalam Go?

Linda Hamilton
Lepaskan: 2024-10-28 04:16:30
asal
580 orang telah melayarinya

How Can Deadlock Occur When Using WaitGroups and Buffered Channels in Go?

Pengesanan Deadlock dalam Go Concurrency dengan WaitGroups

Dalam Go, concurrency selalunya diurus menggunakan saluran dan kumpulan tunggu untuk mengatur gorout. Walau bagaimanapun, adalah penting untuk memahami kemungkinan perangkap yang boleh membawa kepada kebuntuan.

Penerangan Masalah

Pertimbangkan kod berikut yang cuba menggunakan saluran penimbal dan kumpulan tunggu:

<code class="go">package main

import (
    "fmt"
    "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 // Send to channel
            return
        }()
    }
    wg.Wait() // Wait for all goroutines to complete

    for c := range ch {
        fmt.Printf("c is %v", c) // Iterate over channel
    }
}</code>
Salin selepas log masuk

Walaupun menjangkakan saluran akan ditutup secara automatik setelah kapasitinya dicapai, kod ini secara tidak dijangka mengakibatkan ralat jalan buntu.

Penyelesaian

Terdapat dua isu utama yang membawa kepada kebuntuan:

  1. Kapasiti Saluran Tidak Mencukupi: Penampan saluran mempunyai kapasiti 4, manakala terdapat 5 goroutine cuba menulis kepadanya. Ini mengakibatkan situasi di mana goroutin yang menunggu untuk menulis disekat kerana saluran penuh.
  2. Julat Melebihi Saluran Tidak Ditutup: Gelung untuk c := julat ch terus mendengar elemen masuk daripada saluran selama-lamanya, menunggu saluran ditutup. Walau bagaimanapun, kerana tiada goroutine kekal untuk menulis ke saluran, ia tidak pernah ditutup.

Untuk menyelesaikan kebuntuan, dua penyelesaian ialah:

Penyelesaian 1: Meluaskan Kapasiti Saluran dan Penutupan Secara Eksplisit

<code class="go">ch := make(chan []int, 5) // Increase channel capacity
...
wg.Wait()
close(ch) // Close the channel to stop range loop</code>
Salin selepas log masuk

Ini memastikan terdapat ruang yang mencukupi dalam saluran dan menutupnya secara eksplisit, membolehkan gelung julat ditamatkan.

Penyelesaian 2: Keadaan Isyarat Selesai dalam Goroutine

<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() // Signal completion within goroutine
            return
        }()
    }
    go func() {
        for c := range ch {
            fmt.Printf("c is %v\n", c)
            wg.Done() //Decrement count for each iteration
        }
    }()
    wg.Wait()
}</code>
Salin selepas log masuk

Dalam penyelesaian ini, setiap goroutine menandakan siapnya dengan memanggil wg.Done() dalam goroutine itu sendiri. Kumpulan tunggu juga dikurangkan dalam gelung julat untuk setiap lelaran, memastikan wg.Wait() akhirnya selesai dan program ditamatkan.

Atas ialah kandungan terperinci Bagaimanakah Kebuntuan Boleh Berlaku Apabila Menggunakan WaitGroups dan Saluran Penimbalan 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!