Heim > Backend-Entwicklung > Golang > Wie kann es zu einem Deadlock kommen, wenn WaitGroups und gepufferte Kanäle in Go verwendet werden?

Wie kann es zu einem Deadlock kommen, wenn WaitGroups und gepufferte Kanäle in Go verwendet werden?

Linda Hamilton
Freigeben: 2024-10-28 04:16:30
Original
715 Leute haben es durchsucht

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

Deadlock-Erkennung in Go-Parallelität mit WaitGroups

In Go wird die Parallelität häufig mithilfe von Kanälen und Wartegruppen verwaltet, um Goroutinen zu orchestrieren. Es ist jedoch wichtig, potenzielle Fallstricke zu verstehen, die zu Deadlocks führen können.

Problembeschreibung

Betrachten Sie den folgenden Code, der versucht, gepufferte Kanäle und Wartegruppen zu verwenden:

<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>
Nach dem Login kopieren

Obwohl erwartet wird, dass der Kanal automatisch geschlossen wird, sobald seine Kapazität erreicht ist, führt dieser Code unerwartet zu einem Deadlock-Fehler.

Lösung

Es gibt zwei Hauptprobleme, die zum Deadlock führen:

  1. Unzureichende Kanalkapazität: Der Kanalpuffer hat eine Kapazität von 4, während 5 Goroutinen versuchen, darauf zu schreiben. Dies führt zu einer Situation, in der Goroutinen, die auf das Schreiben warten, blockiert werden, weil der Kanal voll ist.
  2. Range Over Unclosed Channel: Die Schleife für c := range ch wartet weiterhin auf eingehende Elemente aus dem Kanal auf unbestimmte Zeit und wartet darauf, dass der Kanal geschlossen wird. Da jedoch keine Goroutinen übrig sind, um in den Kanal zu schreiben, wird er nie geschlossen.

Um den Deadlock zu beheben, gibt es zwei Lösungen:

Lösung 1: Kanalkapazität erweitern und explizit schließen

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

Dadurch wird sichergestellt, dass ausreichend Platz im Kanal vorhanden ist, und dieser wird explizit geschlossen, sodass die Bereichsschleife beendet werden kann.

Lösung 2: Erledigt-Zustand in Goroutine signalisieren

<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>
Nach dem Login kopieren

In dieser Lösung signalisiert jede Goroutine ihren Abschluss, indem sie wg.Done() innerhalb der Goroutine selbst aufruft. Die Wartegruppe wird auch innerhalb der Bereichsschleife für jede Iteration dekrementiert, um sicherzustellen, dass wg.Wait() schließlich abgeschlossen wird und das Programm beendet wird.

Das obige ist der detaillierte Inhalt vonWie kann es zu einem Deadlock kommen, wenn WaitGroups und gepufferte Kanäle in Go verwendet werden?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php.cn
Erklärung dieser Website
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
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage