Deadlock in Go with WaitGroup and Channel
In Go, a deadlock occurs when two or more goroutines wait indefinitely for the other to finish. In this example, we will explore a deadlock issue caused by an insufficient channel buffer and improper syncing of goroutines using a WaitGroup.
The Code
<code class="go">package main import "fmt" import "sync" func main() { ch := make(chan []int, 4) var m []int var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go func() { defer wg.Done() ch <- m return }() } wg.Wait() for c := range ch { fmt.Printf("c is %v", c) } }</code>
The Issue
The code attempts to send 5 values over a buffered channel of size 4. However, when the channel is full, it blocks until a receiver becomes available. Since all goroutines that are sending have finished, none are available to receive from the channel.
Additionally, the goroutine that ranges over the channel (for c := range ch) also remains blocked indefinitely because it expects more values to arrive in the channel even though no more are being sent. This creates a deadlock where both senders and receivers are waiting on each other.
Solution 1: Increase Channel Buffer and Close It
One solution to avoid the deadlock is to increase the channel buffer size to a value greater than or equal to the number of sending goroutines. Additionally, the channel should be closed after all sends are complete, indicating that no more values will be received.
<code class="go">ch := make(chan []int, 5) ... wg.Wait() close(ch)</code>
Solution 2: Perform Done() in Receiving Goroutine
Another solution is to perform Done() in the receiving goroutine instead of in the main function. By doing so, the WaitGroup will not be decremented until the value has been received and consumed by the goroutine:
<code class="go">func main() { ch := make(chan []int, 4) var m []int var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go func() { ch <- m return }() } go func() { for c := range ch { fmt.Printf("c is %v\n", c) wg.Done() } }() wg.Wait() }</code>
The above is the detailed content of How can you avoid deadlock in Go when using WaitGroup and a channel with a limited buffer?. For more information, please follow other related articles on the PHP Chinese website!