Heim >Backend-Entwicklung >Golang >Wie können Sie einen Deadlock in Go vermeiden, wenn Sie WaitGroup und einen Kanal mit begrenztem Puffer verwenden?
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!