解决 Goroutine 死锁
在使用并发 Golang 程序时,可能会遇到死锁错误:“fatal error: all goroutine are sleep -僵局!”。当多个 goroutine 互相等待执行任务时会出现此错误,从而造成死锁情况。
考虑以下代码:
<code class="go">func producer(ch chan int, d time.Duration, num int) { for i := 0; i < num; i++ { ch <- i time.Sleep(d) } } func main() { ch := make(chan int) go producer(ch, 100*time.Millisecond, 2) go producer(ch, 200*time.Millisecond, 5) for { fmt.Println(<-ch) } close(ch) }</code>
此代码创建两个发送值的生产者 goroutine到同一个频道。主协程无限循环地不断从通道接收值。
问题的出现是因为生产者是“短暂的”,在有限的时间后停止发送值,但主协程继续接收值不休。这会造成死锁,因为通道永远不会关闭以发出不再发送任何值的信号。
为了解决此死锁,我们必须确保当所有生产者完成其任务时关闭通道。实现此目的的有效方法是使用同步原语,例如sync.WaitGroup。
这是代码的修改版本:
<code class="go">func producer(ch chan int, d time.Duration, num int, wg *sync.WaitGroup) { defer wg.Done() for i := 0; i < num; i++ { ch <- i time.Sleep(d) } } func main() { wg := &sync.WaitGroup{} ch := make(chan int) wg.Add(1) go producer(ch, 100*time.Millisecond, 2, wg) wg.Add(1) go producer(ch, 200*time.Millisecond, 5, wg) go func() { wg.Wait() close(ch) }() for v := range ch { fmt.Println(v) } }</code>
在此代码中,我们传递了一个sync.WaitGroup。 WaitGroup 到每个生产者 goroutine。每个生产者在开始之前递增等待组,并在完成时递减。主协程使用 wg.Wait() 等待所有生产者完成。一旦所有生产者完成工作,主协程就会关闭通道。
此解决方案确保只有在所有生产者完成工作后才关闭通道,从而防止出现死锁情况。
以上是Golang中使用Goroutines和Channel时如何防止死锁?的详细内容。更多信息请关注PHP中文网其他相关文章!