Heim  >  Artikel  >  Backend-Entwicklung  >  Wie kann ein Deadlock in Golang bei der Verwendung von Goroutinen und Kanälen verhindert werden?

Wie kann ein Deadlock in Golang bei der Verwendung von Goroutinen und Kanälen verhindert werden?

Susan Sarandon
Susan SarandonOriginal
2024-10-27 06:48:29393Durchsuche

How to Prevent Deadlock in Golang When Using Goroutines and Channels?

Goroutinen-Deadlock lösen

Bei der Arbeit mit gleichzeitigen Golang-Programmen kann ein Deadlock-Fehler auftreten: „Schwerwiegender Fehler: Alle Goroutinen schlafen – Deadlock!". Dieser Fehler tritt auf, wenn mehrere Goroutinen aufeinander warten, um eine Aufgabe auszuführen, wodurch eine Deadlock-Situation entsteht.

Bedenken Sie den folgenden Code:

<code class="go">func producer(ch chan int, d time.Duration, num int) {
    for i := 0; i < num; i++ {
        ch <- i
        time.Sleep(d)
    }
}

func main() {
    ch := make(chan int)

    go producer(ch, 100*time.Millisecond, 2)
    go producer(ch, 200*time.Millisecond, 5)

    for {
        fmt.Println(<-ch)    
    }

    close(ch)
}</code>

Dieser Code erstellt zwei Produzenten-Goroutinen, die Werte senden zum gleichen Kanal. Die Haupt-Goroutine empfängt kontinuierlich Werte vom Kanal in einer Endlosschleife.

Das Problem entsteht, weil die Produzenten „kurzlebig“ sind und nach einer endlichen Zeitspanne keine Werte mehr senden, die Haupt-Goroutine jedoch weiterhin Werte empfängt endlos. Dadurch entsteht ein Deadlock, da der Kanal nie geschlossen wird, um zu signalisieren, dass keine weiteren Werte gesendet werden.

Um diesen Deadlock zu lösen, müssen wir sicherstellen, dass der Kanal geschlossen wird, wenn alle Produzenten ihre Aufgaben abgeschlossen haben. Der effiziente Weg, dies zu erreichen, besteht darin, ein Synchronisierungsprimitiv wie eine sync.WaitGroup zu verwenden.

Hier ist eine modifizierte Version des Codes:

<code class="go">func producer(ch chan int, d time.Duration, num int, wg *sync.WaitGroup) {
    defer wg.Done()

    for i := 0; i < num; i++ {
        ch <- i
        time.Sleep(d)
    }
}

func main() {
    wg := &sync.WaitGroup{}
    ch := make(chan int)

    wg.Add(1)
    go producer(ch, 100*time.Millisecond, 2, wg)
    wg.Add(1)
    go producer(ch, 200*time.Millisecond, 5, wg)

    go func() {
        wg.Wait()
        close(ch)
    }()

    for v := range ch {
        fmt.Println(v)
    }
}</code>

In diesem Code übergeben wir eine Synchronisierung. WaitGroup für jede Produzenten-Goroutine. Jeder Produzent erhöht die Wartegruppe vor dem Start und verringert sie am Ende. Die Haupt-Goroutine wartet auf den Abschluss aller Produzenten, die wg.Wait() verwenden. Sobald alle Produzenten fertig sind, schließt die Haupt-Goroutine den Kanal.

Diese Lösung stellt sicher, dass der Kanal erst geschlossen wird, nachdem alle Produzenten ihre Arbeit abgeschlossen haben, wodurch eine Deadlock-Situation verhindert wird.

Das obige ist der detaillierte Inhalt vonWie kann ein Deadlock in Golang bei der Verwendung von Goroutinen und Kanälen verhindert werden?. 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