go 通道channel使用for-range造成死锁问题

本文详细解释了Golang中使用for-range遍历channel可能导致死锁的原因,并提供了解决方案,同时讨论了生产者消费者模型和避免阻塞的技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如下代码,运行时会造成死锁

func main()  {
	var t = make(chan int)
	go func() {
		for i := 1;i<=10;i++ {
			t <- i
		}
	}()

	for t1 := range t{
		fmt.Println(t1)
	}
	fmt.Println("ok")
}

原因是:for range是阻塞式读取channel,只有channel close之后才会结束,否则会一直读取,通道里没有值了,还继续读取就会阻塞,程序就会报死锁。

改成如下即可:

func main()  {
	var t = make(chan int)
	go func() {
		for i := 1;i<=100;i++ {
			t <- i
		}
		close(t)
	}()

	for t1 := range t{
		fmt.Println(t1)
	}

	fmt.Println("ok")
}

有时会没有输出,原因是主协程已经退出了,此时我们只要加个sleep即可

golang中的channel思路就是生产者消费者,无论生产者写入数据还是消费者读取数据都是阻塞的,理解这个的思路要基于阻塞这个前提。

fori这种形式是自己判断从channel中读取多少次
for range 这种就是是runtime帮我们来判断了,他的判断标准是 close(ch)

你的fori改成多一次循环同样会被go判定为 deadlock
因为最后一次的读取会一直阻塞在那里,原因是生产者不再生产了,消费者还阻塞在那里等待。go判断到这个会一直阻塞在这里的场景就直接抛出错误退出了,否则这个进程就一直hang在这里还不易被发现。

导致这种错误的情况有两种
生产者
没有消费者消费channel中的数据,channel中的数据已经填充满了,但是还在往里写入,此刻是要阻塞等待的,由于没有消费者,这个阻塞会一直阻塞下去
消费者
生产者不再生产数据了,也就是是 channel 中会一直为空了,但是消费者还在读取channel中的数据,这个读取也是阻塞等待的,channel中不会再有数据,这个等待也是会一直等待下去

参考:go通道channel使用for-range造成死锁,而使用for计数器迭代却不会? - SegmentFault 思否

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值