Heim  >  Artikel  >  Backend-Entwicklung  >  Wie vermeide ich Deadlocks bei der Verwendung von sync.WaitGroup mit externen Funktionen in Go?

Wie vermeide ich Deadlocks bei der Verwendung von sync.WaitGroup mit externen Funktionen in Go?

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2024-11-05 22:03:02873Durchsuche

How to Avoid Deadlocks When Using sync.WaitGroup with External Functions 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!

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