Heim >Backend-Entwicklung >Golang >Wie können Go-Deadlocks behoben werden, die durch asynchrone Vorgänge und leere Kanäle verursacht werden?
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) }()
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") }
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!