Heim > Backend-Entwicklung > Golang > Wie können Go-Deadlocks behoben werden, die durch asynchrone Vorgänge und leere Kanäle verursacht werden?

Wie können Go-Deadlocks behoben werden, die durch asynchrone Vorgänge und leere Kanäle verursacht werden?

Barbara Streisand
Freigeben: 2024-12-11 18:04:12
Original
241 Leute haben es durchsucht

How to Resolve Go Deadlocks Caused by Asynchronous Operations and Empty Channels?

Deadlock in Go: „Alle Go-Routinen schlafen“

Beim Ausführen des bereitgestellten Codes kommt es aufgrund seines asynchronen Ausführungsmodells zu einem Deadlock Verwendung von Goroutinen. Das Problem tritt auf, wenn die UnloadTrucks-Funktion aufgerufen wird, bevor LKWs an den Kanal gesendet wurden. Dies führt dazu, dass der Kanal leer bleibt und die Sender-Goroutinen an der Zeile ch <- tr blockieren. Da die Absender-Goroutinen darauf warten, LKWs zu senden, können sie den Kanal nicht schließen, und die UnloadTrucks-Funktion, die auf den Empfang von LKWs wartet, bleibt auf unbestimmte Zeit hängen.

Lösung: WaitGroup zum Schließen des Kanals verwenden

Um den Deadlock zu beheben, können wir den Kanal ch schließen, nachdem alle Goroutinen mit dem Senden von Lastwagen fertig sind. Dies kann durch die Einführung einer WaitGroup erreicht werden, einem Synchronisierungsprimitiv, das die Anzahl ausstehender Goroutinen verfolgt:

go func() {
    wg.Wait()
    close(ch)
}()
Nach dem Login kopieren

Diese Goroutine wartet, bis alle anderen Goroutinen ihre Aufgaben zuvor abgeschlossen haben (signalisiert durch den Wait()-Aufruf). den Kanal schließen. Auf diese Weise kann die UnloadTrucks-Funktion ordnungsgemäß beendet werden, wenn alle LKWs gesendet wurden.

Überarbeiteter Code:

package main

import (
    "fmt"
    "sync"
    "time"
)

type Item struct {
    name string
}

type Truck struct {
    Cargo []Item
    name  string
}

func UnloadTrucks(c chan Truck) {

    for t := range c {
        fmt.Printf("%s has %d items in cargo: %s\n", t.name, len(t.Cargo), t.Cargo[0].name)
    }

}

func main() {
    trucks := make([]Truck, 2)

    ch := make(chan Truck)

    var wg sync.WaitGroup
    for i, _ := range trucks {

        trucks[i].name = fmt.Sprintf("Truck %d", i+1)

        fmt.Printf("Building %s\n", trucks[i].name)
    }

    for t := range trucks {
        go func(tr Truck) {

            itm := Item{}
            itm.name = "Groceries"

            fmt.Printf("Loading %s\n", tr.name)
            tr.Cargo = append(tr.Cargo, itm)
            ch <- tr
            wg.Done()

        }(trucks[t])
        wg.Add(1)
    }

    time.Sleep(50 * time.Millisecond)
    fmt.Println("Unloading Trucks")
    UnloadTrucks(ch)

    fmt.Println("Done")
}
Nach dem Login kopieren

Mit diesem geänderten Code wird der Deadlock wird eliminiert, da die UnloadTrucks-Funktion garantiert alle LKWs empfängt, bevor der Kanal geschlossen wird. Dadurch wird sichergestellt, dass alle Goroutinen ihre Aufgaben ordnungsgemäß erledigen und das Programm ohne unerwartete Unterbrechungen ausgeführt wird.

Das obige ist der detaillierte Inhalt vonWie können Go-Deadlocks behoben werden, die durch asynchrone Vorgänge und leere Kanäle verursacht werden?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php.cn
Erklärung dieser Website
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
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage