Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimanakah anda boleh mengelakkan kebuntuan dalam Go apabila menggunakan WaitGroup dan saluran dengan penimbal terhad?

Bagaimanakah anda boleh mengelakkan kebuntuan dalam Go apabila menggunakan WaitGroup dan saluran dengan penimbal terhad?

Mary-Kate Olsen
Mary-Kate Olsenasal
2024-10-27 01:21:02959semak imbas

How can you avoid deadlock in Go when using WaitGroup and a channel with a limited buffer?

Kebuntuan dalam Go dengan WaitGroup dan Saluran

Dalam Go, kebuntuan berlaku apabila dua atau lebih gorout menunggu selama-lamanya untuk yang lain selesai. Dalam contoh ini, kami akan meneroka isu kebuntuan yang disebabkan oleh penimbal saluran yang tidak mencukupi dan penyegerakan goroutine yang tidak betul menggunakan WaitGroup.

Kod

<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>

Isunya

Kod cuba menghantar 5 nilai melalui saluran penimbal bersaiz 4. Walau bagaimanapun, apabila saluran penuh, ia menyekat sehingga penerima tersedia. Memandangkan semua goroutine yang menghantar telah selesai, tiada satu pun yang tersedia untuk diterima daripada saluran.

Selain itu, goroutine yang berjulat di atas saluran (untuk c := julat ch) juga kekal disekat selama-lamanya kerana ia menjangkakan lebih banyak nilai untuk tiba di saluran walaupun tiada lagi yang dihantar. Ini mewujudkan kebuntuan di mana kedua-dua penghantar dan penerima sedang menunggu antara satu sama lain.

Penyelesaian 1: Tingkatkan Penampan Saluran dan Tutupnya

Satu penyelesaian untuk mengelakkan kebuntuan adalah dengan meningkatkan saiz penimbal saluran kepada nilai yang lebih besar daripada atau sama dengan bilangan goroutin penghantaran. Selain itu, saluran hendaklah ditutup selepas semua penghantaran selesai, menunjukkan bahawa tiada lagi nilai akan diterima.

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

Penyelesaian 2: Lakukan Selesai() dalam Menerima Goroutine

Penyelesaian lain ialah melakukan Done() dalam goroutine penerima dan bukannya dalam fungsi utama. Dengan berbuat demikian, WaitGroup tidak akan dikurangkan sehingga nilai telah diterima dan digunakan oleh 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
            return
        }()
    }
    go func() {
        for c := range ch {
            fmt.Printf("c is %v\n", c)
            wg.Done()
        }
    }()
    wg.Wait()
}</code>

Atas ialah kandungan terperinci Bagaimanakah anda boleh mengelakkan kebuntuan dalam Go apabila menggunakan WaitGroup dan saluran dengan penimbal terhad?. 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