Golang中遇到无法理解的死锁问题如何解决
Golang中遇到无法理解的死锁问题如何解决
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int, 10)
i := 100
go func() {
ch <- i
i++
time.Sleep(time.Second * 2)
}()
for i := range ch {
println(i)
}
fmt.Println("end...")
}
致命错误:所有goroutine都处于休眠状态 - 死锁!
我无法理解为什么这段代码会失败。 我认为死锁是绝不可能发生的。
更多关于Golang中遇到无法理解的死锁问题如何解决的实战教程也可以访问 https://www.itying.com/category-94-b0.html
欢迎。请随时"标记为已解决"来关闭该工单。
更多关于Golang中遇到无法理解的死锁问题如何解决的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
哦!感谢您的友好回复 🙂
我完全明白了。谢谢!
感谢回复 🙂
fmt.Println 是正确的,不是 println。
我想重复发送一些值(100,101,102 … N),但你的代码只发送一次就结束了。我该如何构建接收器(range 循环)和发送器(go 协程)?
欢迎来到 Golang 桥社区!🚀🎆
1. 忘记关闭通道
如果你正在使用通道循环(for i := range ch),你需要在发送端完成操作后关闭通道。在你的子例程中,你将值传入通道并休眠。因此,正确的修正应该是:
...
go func() {
ch <- i
i++
time.Sleep(time.Second * 2)
close(ch)
}
...
编辑:
原因:main 函数永远等待
main 函数持续等待通道关闭,以便安全地继续执行 range 循环。然而,协程没有发送关闭信号就结束了,导致 for 循环永远等待(死锁等待)。这就是你遇到死锁的原因。
2. 附注:错误代码
在你的 for 循环中,println(i) 是一个未知函数。应该是 fmt.Println(i) 吗?
交叉检查
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int, 10)
i := 100
go func() {
ch <- i
i++
time.Sleep(time.Second * 2)
close(ch)
}()
for i := range ch {
fmt.Println(i)
}
fmt.Println("[ END ]")
}
// 输出:
// 100
// [ END ]
我想重复发送一些值(100,101,102…N),但你的代码只发送一次就结束了。如何构建接收器(range循环)和发送器(协程)?
这需要从清晰明确的数据传输并发规划开始。你可以使用流程图或伪代码。以下是使用伪代码的示例:
进程0(main):
- 创建具有10个缓冲空间的通道
- 将i上限设置为100
- 启动
p1进程 - 开始从通道读取直到其关闭
- 终止整个程序
进程1(命名为p1):
- 从0到上限进行循环,命名为
value - 对每个
value,将value发送到通道然后休眠2秒 - 完成后关闭通道
- 终止
p1进程
关键词:
- 必须明确"谁在何时做什么",每个进程的每个步骤都要清晰。
你可以自己尝试实现。我已重新编写了匹配伪代码的示例,请自觉遵守要求,好吗?
示例答案:
package main
import (
"fmt"
"time"
)
func p1(limit int, ch chan int) {
for value := 0; value < limit; value++ {
ch <- value
time.Sleep(time.Second * 2)
}
// done with operation, close channel.
close(ch)
}
func main() {
ch := make(chan int, 10)
i := 100
// start p1 process
go p1(i, ch)
// read from channel
for i := range ch {
fmt.Println(i)
}
fmt.Println("[ END ]")
}

