Heim  >  Artikel  >  Backend-Entwicklung  >  Wie vermeidet man Deadlocks in Go-Goroutinen, wenn die Produzenten nur von kurzer Dauer sind?

Wie vermeidet man Deadlocks in Go-Goroutinen, wenn die Produzenten nur von kurzer Dauer sind?

Linda Hamilton
Linda HamiltonOriginal
2024-10-25 07:09:02784Durchsuche

How to Avoid Deadlock in Go Goroutines When Producers Are Short-Lived?

Deadlock in Go-Goroutinen auflösen

Bei der gleichzeitigen Programmierung tritt ein Deadlock auf, wenn mehrere Goroutinen auf unbestimmte Zeit darauf warten, dass einander Vorgänge abschließt, wodurch die Operation effektiv angehalten wird Programm. Dieser Artikel befasst sich mit einem bestimmten Deadlock, der bei der Go-Parallelität auftritt, wie in der ursprünglichen Frage beschrieben:

<code class="go">package main

import (
    "fmt"
    "time"
)

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 löst aufgrund der folgenden Faktoren einen Deadlock-Fehler aus:

  • Die Produzenten , die Werte an den Kanal senden, sind nur von kurzer Dauer und produzieren schließlich keine Daten mehr.
  • Die endlose for-Schleife in der Hauptfunktion empfängt kontinuierlich Werte vom Kanal ohne Beendigungsbedingung.
  • Die Der Kanal wird nach der Endlosschleife geschlossen, sodass keine weiteren Werte mehr zum Empfang verfügbar sind.

Lösung: Koordinierte Beendigung

Um einen Deadlock zu vermeiden, müssen die Produzenten koordiniert werden, um den Abschluss zu signalisieren, und der Kanal muss vom letzten Produzenten geschlossen werden. Hier ist eine effiziente Lösung, die eine sync.WaitGroup zur Koordination verwendet:

<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 dieser Lösung:

  • Wir erhöhen die WaitGroup für jeden Produzenten.
  • Jeden Produzenten dekrementiert die WaitGroup nach Abschluss durch eine Defer-Anweisung.
  • Eine Goroutine wartet darauf, dass die WaitGroup Null erreicht (was bedeutet, dass alle Produzenten fertig sind) und schließt den Kanal.
  • Die Hauptschleife verwendet einen for-Bereich Konstrukt, um die auf dem Kanal gesendeten Werte zu durchlaufen, bevor er geschlossen wird.

Das obige ist der detaillierte Inhalt vonWie vermeidet man Deadlocks in Go-Goroutinen, wenn die Produzenten nur von kurzer Dauer sind?. 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