Heim  >  Artikel  >  Backend-Entwicklung  >  Wie kann ich einen Deadlock verhindern, wenn ich WaitGroups und gepufferte Kanäle in Go verwende?

Wie kann ich einen Deadlock verhindern, wenn ich WaitGroups und gepufferte Kanäle in Go verwende?

Linda Hamilton
Linda HamiltonOriginal
2024-10-26 18:10:02299Durchsuche

How can I prevent deadlock when using WaitGroups and buffered channels in Go?

Deadlock in Go: WaitGroup und gepufferte Kanäle

In Go tritt ein Deadlock auf, wenn gleichzeitige Goroutinen auf unbestimmte Zeit auf den Abschluss anderer warten. Eine häufige Ursache für Deadlocks ist die Verwendung von WaitGroups und gepufferten Kanälen.

Beispiel für einen Deadlock

Beachten Sie den folgenden 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 // Sending to a full channel
            return
        }()
    }
    wg.Wait()

    for c := range ch {
        fmt.Printf("c is %v", c)
    }
}</code>

Dieser Code beabsichtigt, 5 leere Slices an einen gepufferten Kanal mit einer Kapazität von 4 zu senden und dann aus dem Kanal zu lesen, nachdem alle Goroutinen abgeschlossen sind. Der Code führt jedoch zu einem Deadlock-Fehler.

Ursache des Deadlocks

Der Deadlock entsteht aufgrund zweier Probleme:

  1. Unzureichender Kanalpuffer: Der Kanal hat eine Kapazität von 4, was zu klein für die 5 Goroutinen ist, die versuchen, Daten zu senden. Wenn der Kanal voll ist, werden nachfolgende Goroutinen, die darauf warten, Daten zu senden (Zeile 15), auf unbestimmte Zeit blockiert.
  2. Kanaliteration blockieren: Die Schleife, die über den Kanal iteriert (Zeilen 22–24), blockiert auf unbestimmte Zeit, da darauf gewartet wird, dass weitere Elemente auf dem Kanal eintreffen. Da alle Goroutinen mit dem Senden von Daten fertig sind und keine weiteren Daten erwartet werden, wird diese Iteration nie ohne eine entsprechende Goroutine-Lesung vom Kanal abgeschlossen.

Lösung

Um den Deadlock zu beheben, nehmen Sie eine der folgenden Änderungen vor:

Lösung 1:

Erhöhen Sie die Kanalkapazität auf 5 (oder mehr) und schließen Sie ihn, nachdem alle Daten gesendet wurden :

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

Lösung 2:

Starten Sie eine separate Goroutine, um vom Kanal zu lesen und die Haupt-Goroutine zu benachrichtigen, wenn alle Daten empfangen wurden:

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

Das obige ist der detaillierte Inhalt vonWie kann ich einen Deadlock verhindern, wenn ich WaitGroups und gepufferte Kanäle in Go verwende?. 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