Go 中的死锁:WaitGroup 和缓冲通道
在 Go 中,当并发 goroutine 无限期地等待彼此完成时,就会发生死锁。死锁的一个常见原因涉及使用 WaitGroups 和缓冲通道。
死锁示例
考虑以下代码:
<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 // Sending to a full channel return }() } wg.Wait() for c := range ch { fmt.Printf("c is %v", c) } }</code>
此代码打算将 5 个空切片发送到容量为 4 的缓冲通道,然后在所有 goroutine 完成后从通道中读取。但是,该代码会导致死锁错误。
死锁的原因
死锁是由于两个问题引起的:
解决方案
要解决死锁,请进行以下修改之一:
解决方案 1:
将通道容量增加到 5(或更多)并在发送完所有数据后将其关闭:
<code class="go">ch := make(chan []int, 5) ... wg.Wait() close(ch)</code>
解决方案2:
启动一个单独的goroutine从通道读取数据,并在接收到所有数据后通知主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 wg.Done() }() } go func() { for c := range ch { fmt.Printf("c is %v\n", c) wg.Done() } }() wg.Wait() }</code>
以上是在 Go 中使用 WaitGroups 和缓冲通道时如何防止死锁?的详细内容。更多信息请关注PHP中文网其他相关文章!