
goroutine 死锁: 为什么会出现 fatal error
在并发编程中,goroutine 死锁是一个常见问题。让我们通过一个代码示例来理解为什么会出现 "fatal error: all goroutines are asleep - deadlock!"。
func main() {
a := make(chan bool)
b := make(chan bool)
defer close(a)
defer close(b)
var wg sync.waitgroup
wg.add(2)
go func() {
for i := 0; i < 10; i += 2 {
if <-a {
fmt.println(i)
b <- true
}
}
wg.done()
}()
go func() {
for i := 1; i < 10; i += 2 {
if <-b {
fmt.println(i)
a <- true
}
}
wg.done()
}()
a <- true
wg.wait()
}这个代码使用两个 chan (a 和 b) 在两个 goroutine 之间进行通信。它使用 waitgroup 为主 goroutine 等待两个 goroutine 完成。
问题出在 b goroutine 执行的最后一次循环迭代。在这个迭代中,b goroutine 发送 true 到 a 并退出。但是,此时 a goroutine 已经没有机会接收该消息,因为它正在等待 b goroutine 发送 true。因此,程序进入死锁状态。
要解决此问题,可以在 b goroutine 的最后一次迭代中添加一个额外的接收操作。这将确保 a goroutine 有机会处理 b goroutine 的最后一条消息,从而避免死锁。
修改后的代码如下:
func main() {
A := make(chan bool)
B := make(chan bool)
defer close(A)
defer close(B)
var wg sync.WaitGroup
wg.Add(2)
go func() {
for i := 0; i < 10; i += 2 {
if <-A {
fmt.Println(i)
B <- true
}
}
<-A // 额外的接收操作
wg.Done()
}()
go func() {
for i := 1; i < 10; i += 2 {
if <-B {
fmt.Println(i)
A <- true
}
}
wg.Done()
}()
A <- true
wg.Wait()
}以上就是Goroutine 死锁:为什么会出现 "fatal error: all goroutines are asleep - deadlock!"?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号