In diesem Artikel analysieren wir die Ursachen hinter dem „Deadlock“! Fehler, der aus einer Deadlock-Situation mit Go-Kanälen im folgenden Codeausschnitt entsteht:
package main import ( "fmt" "sync" ) func push(c chan int, wg sync.WaitGroup) { for i := 0; i < 5; i++ { c <- i } wg.Done() } func pull(c chan int, wg sync.WaitGroup) { for i := 0; i < 5; i++ { result, ok := <-c fmt.Println(result, ok) } wg.Done() } func main() { var wg sync.WaitGroup wg.Add(2) c := make(chan int) go push(c, wg) go pull(c, wg) wg.Wait() }
Beim Ausführen dieses Codes tritt der folgende Fehler auf:
throw: all goroutines are asleep - deadlock!
Der Deadlock tritt auf, weil Strukturen, wie die sync.WaitGroup in diesem Code, als Wert und nicht als Referenz übergeben werden. Das bedeutet, dass wir, wenn wir die WaitGroup an unsere Funktionen übergeben (Push und Pull), tatsächlich eine Kopie der WaitGroup anstelle des ursprünglichen Objekts übergeben.
Infolgedessen arbeitet jede Funktion an ihrer eigenen Kopie der WaitGroup, und wenn sie wg.Done() aufrufen, dekrementieren sie ihre eigenen Kopien. Dadurch wird die ursprüngliche WaitGroup, auf die unsere Haupt-Goroutine wartet, nicht aktualisiert, was zu einem Deadlock führt.
Um dieses Problem zu beheben, müssen wir den Zeiger übergeben zur WaitGroup anstelle des Werts. Dadurch wird sichergestellt, dass sowohl die Push- als auch die Pull-Funktion auf derselben Instanz der WaitGroup arbeiten und ihre Aufrufe von wg.Done() sich auf das ursprüngliche Objekt auswirken.
Hier ist eine korrigierte Version des Codes:
package main import ( "fmt" "sync" ) func push(c chan int, wg *sync.WaitGroup) { for i := 0; i < 5; i++ { c <- i } wg.Done() } func pull(c chan int, wg *sync.WaitGroup) { for i := 0; i < 5; i++ { result, ok := <-c fmt.Println(result, ok) } wg.Done() } func main() { var wg sync.WaitGroup wg.Add(2) c := make(chan int) go push(c, &wg) go pull(c, &wg) wg.Wait() }
Durch diese Änderung übergeben wir nun den Zeiger auf die WaitGroup an unsere Funktionen und stellen so sicher, dass beide am selben Objekt arbeiten und dessen Status korrekt aktualisieren. Dadurch wird die Deadlock-Situation beseitigt und unser Programm kann fehlerfrei ausgeführt werden.
Das obige ist der detaillierte Inhalt vonWie behebe ich Deadlock-Fehler in Go-Kanälen bei Verwendung von sync.WaitGroup?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!