Heim  >  Artikel  >  Backend-Entwicklung  >  Wie können Sie einen Deadlock in Go vermeiden, wenn Sie WaitGroup und einen Kanal mit begrenztem Puffer verwenden?

Wie können Sie einen Deadlock in Go vermeiden, wenn Sie WaitGroup und einen Kanal mit begrenztem Puffer verwenden?

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2024-10-27 01:21:02959Durchsuche

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

Deadlock in Go mit WaitGroup und Channel

In Go tritt ein Deadlock auf, wenn zwei oder mehr Goroutinen auf unbestimmte Zeit auf den Abschluss der anderen warten. In diesem Beispiel untersuchen wir ein Deadlock-Problem, das durch einen unzureichenden Kanalpuffer und eine unsachgemäße Synchronisierung von Goroutinen mithilfe einer WaitGroup verursacht wird.

Der Code

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

Das Problem

Der Code versucht, 5 Werte über einen gepufferten Kanal der Größe 4 zu senden. Wenn der Kanal jedoch voll ist, blockiert er, bis ein Empfänger verfügbar wird. Da alle Goroutinen, die senden, fertig sind, sind keine mehr für den Empfang vom Kanal verfügbar.

Außerdem bleibt die Goroutine, die sich über den Kanal erstreckt (für c := range ch), ebenfalls auf unbestimmte Zeit blockiert, da sie mehr Werte erwartet im Kanal ankommen, obwohl keine weiteren gesendet werden. Dadurch entsteht ein Deadlock, bei dem sowohl Sender als auch Empfänger aufeinander warten.

Lösung 1: Kanalpuffer erhöhen und schließen

Eine Lösung, um den Deadlock zu vermeiden, besteht darin, Folgendes zu tun: Erhöhen Sie die Größe des Kanalpuffers auf einen Wert, der größer oder gleich der Anzahl der sendenden Goroutinen ist. Darüber hinaus sollte der Kanal geschlossen werden, nachdem alle Sendungen abgeschlossen sind, was darauf hinweist, dass keine weiteren Werte empfangen werden.

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

Lösung 2: Führen Sie Done() in der empfangenden Goroutine aus

Eine andere Lösung besteht darin, Done() in der empfangenden Goroutine statt in der Hauptfunktion auszuführen. Dadurch wird die WaitGroup erst dekrementiert, wenn der Wert von der Goroutine empfangen und verbraucht wurde:

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

Das obige ist der detaillierte Inhalt vonWie können Sie einen Deadlock in Go vermeiden, wenn Sie WaitGroup und einen Kanal mit begrenztem Puffer verwenden?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn