Deadlock in Go: "All Goroutines Are Asleep"
When working with goroutines, it's crucial to manage channel operations effectively to avoid deadlocks. This occurs when all goroutines are blocked indefinitely, leading to a deadlock situation.
Understanding the Code
Let's examine the provided 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) 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 }(trucks[t]) } time.Sleep(50 * time.Millisecond) fmt.Println("Unloading Trucks") UnloadTrucks(ch) fmt.Println("Done") }
This code creates a channel ch of type Truck and launches two goroutines to simulate loading trucks with groceries and sending them to the channel. It then calls UnloadTrucks to retrieve and print the trucks' contents.
Cause of Deadlock
The issue lies in the absence of a mechanism to close the ch channel. When all goroutines have sent their trucks to the channel, there's no signal to terminate the loop in UnloadTrucks. This means that ch keeps listening for values that never arrive, resulting in a deadlock.
Solution
To resolve the deadlock, we need to explicitly close the ch channel when the loading goroutines are complete. We can use a sync.WaitGroup to count the running goroutines and close the channel when all have finished:
var wg sync.WaitGroup go func() { wg.Wait() close(ch) }() UnloadTrucks(ch)
This modification ensures that UnloadTrucks will terminate once all goroutines have finished loading trucks. The Wait function blocks until the WaitGroup counter reaches zero, indicating that all goroutines have completed their work. Closing the channel signals to UnloadTrucks that there are no more trucks to be received, allowing it to gracefully exit the loop.
The above is the detailed content of How to Resolve Deadlocks in Go When All Goroutines Are Asleep?. For more information, please follow other related articles on the PHP Chinese website!