Heim > Artikel > Backend-Entwicklung > Wie vermeide ich Deadlocks bei der Verwendung von sync.WaitGroup mit externen Funktionen in Go?
Best Practice für die Nutzung von sync.WaitGroup mit externen Funktionen
Beim Umgang mit Parallelität in Go ist es entscheidend, sync.WaitGroup effektiv zu nutzen. Dieser Artikel befasst sich mit einem häufigen Problem, das beim Übergeben einer Wartegruppe als Argument an eine externe Funktion auftritt.
Problem:
Bedenken Sie den folgenden Code:
<code class="go">package main import ( "fmt" "sync" ) func main() { ch := make(chan int) var wg sync.WaitGroup wg.Add(2) go Print(ch, wg) // go func(){ for i := 1; i <= 11; i++ { ch <- i } close(ch) defer wg.Done() }() wg.Wait() //deadlock here } // Print prints all numbers sent on the channel. // The function returns when the channel is closed. func Print(ch <-chan int, wg sync.WaitGroup) { for n := range ch { // reads from channel until it's closed fmt.Println(n) } defer wg.Done() }</code>
In diesem Code tritt in der angegebenen Zeile ein Deadlock auf, der dazu führt, dass das Programm nur von 1 bis 10 druckt, anstatt 11 zu erreichen. Der Fehler entsteht durch die Übergabe einer Kopie von sync.WaitGroup an die Print-Methode, was dies behindert der erwartete Aufruf der Done-Methode.
Lösung 1:
Um dieses Problem zu beheben, übergeben Sie stattdessen einen Zeiger an die Wartegruppe:
<code class="go">package main import ( "fmt" "sync" ) func main() { ch := make(chan int) var wg sync.WaitGroup wg.Add(2) go Print(ch, &wg) go func() { for i := 1; i <= 11; i++ { ch <- i } close(ch) defer wg.Done() }() wg.Wait() //deadlock here } func Print(ch <-chan int, wg *sync.WaitGroup) { for n := range ch { // reads from channel until it's closed fmt.Println(n) } defer wg.Done() }</code>
Durch die Übergabe der Adresse von wg wird sichergestellt, dass die Print-Methode die Done-Methode in der Wartegruppe aufruft, auf die in der Hauptfunktion gewartet wird.
Lösung 2: Vereinfachte Druckmethode
Alternativ kann die Print-Methode durch Entfernen des WaitGroup-Arguments vereinfacht werden, da sie keine Kenntnisse über Warteoperationen erfordert:
<code class="go">package main import ( "fmt" ) func main() { ch := make(chan int) go func() { for i := 1; i <= 11; i++ { ch <- i } close(ch) }() for n := range ch { // reads from channel until it's closed fmt.Println(n) } } </code>
In diesem Szenario empfängt die Haupt-Goroutine den Kanal direkt und druckt seine Werte, ohne eine Wartegruppe einzubeziehen. Dieser Ansatz behält die gewünschte Funktionalität bei und macht eine WaitGroup-Verwaltung innerhalb der Print-Methode überflüssig.
Fazit:
Wenn sync.WaitGroup als Argument an externe Funktionen übergeben wird, Es muss unbedingt sichergestellt werden, dass die Funktion den korrekten Verweis auf die Wartegruppe erhält, auf die gewartet wird. Durch die Umgestaltung der Funktion zur direkten Verarbeitung von Wartegruppen oder die Übergabe eines Zeigers an die Wartegruppe können Deadlock-Fehler wirksam verhindert und eine ordnungsgemäße Parallelitätskontrolle sichergestellt werden.
Das obige ist der detaillierte Inhalt vonWie vermeide ich Deadlocks bei der Verwendung von sync.WaitGroup mit externen Funktionen in Go?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!