Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimanakah Kebuntuan Boleh Berlaku Apabila Menggunakan WaitGroups dan Saluran Penimbalan dalam Go?

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

Linda Hamilton
Linda Hamiltonasal
2024-10-28 04:16:30564semak imbas

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>

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>

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>

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!

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