如何获取无缓冲通道中的元素数量
Posted
技术标签:
【中文标题】如何获取无缓冲通道中的元素数量【英文标题】:How to get the number of elements in an unbuffered channel 【发布时间】:2017-06-11 03:17:51 【问题描述】:我的程序处于死锁状态,我想调试它并告诉无缓冲通道中有多少元素,在 Go 中有什么方法可以做到这一点?下面的代码没有像我预期的那样输出 2 (进一步死锁,这也是我找不到原因的原因)
package main
import "fmt"
func main()
channel := make(chan string)
done_channel := make(chan bool)
go func()
channel <- "value"
channel <- "value"
fmt.Println(len(channel))
done_channel <- true
()
variable := <- channel
fmt.Println(variable)
ok := <- done_channel
fmt.Println(ok)
【问题讨论】:
一个无缓冲的通道不包含任何元素,它是无缓冲的。 @JimB 我在一个通道上无限阻塞的情况下,我想调试它以查看通道中是否有任何东西,因为从单步执行代码来看,它确实出现了元素已发送到频道,您建议我如何执行此操作? 无缓冲通道是同步的,只有在有接收者的情况下才能发送。通道不存储(缓冲)任何东西。您正在阻止,因为您尝试发送 2 个值,但只接收 1 个。 @JoelCornett:这是个坏主意。您不仅在通道切片上添加了竞争条件,阻止了同时在多个通道上进行选择的能力,并且失去了通过关闭通道来停止范围的能力,而且您的接收循环默认为使用 100% 的繁忙循环CPU,最终会阻塞调度器。 @JoelCornett:您的假设不正确,唯一的原子操作是通过 sync/atomic 包。这不是本次谈话的地方——首先仔细阅读 go memory 模型文档和我链接的文章。 【参考方案1】:Go 运行时有一个您刚刚遇到的死锁检测器。检测器为您提供解决问题所需的所有信息。您无需分析通道长度。
让我们看看你的程序的输出
value
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
/home/grzesiek/test.go:16 +0x17e
goroutine 5 [chan send]:
main.main.func1(0xc42001a0c0, 0xc42001a120)
/home/grzesiek/test.go:10 +0x99
created by main.main
/home/grzesiek/test.go:13 +0x9c
exit status 2
这是说所有的 goroutine 都处于睡眠状态(阻塞)并且不可能有任何进展。被阻塞的 goroutine 与阻塞操作和导致阻塞的行一起列出。
Goroutine 1 (main) 正在尝试从第 16 行的通道 done_channel
读取。
Goroutine 5(由函数调用运算符 ()
在第 13 行创建)正在尝试在第 10 行写入通道 channel
。它永远不会走得更远,因为通道的另一侧没有 goroutine。因此它永远不会写信给done_channel
。
程序被阻塞,因为没有goroutine可以走得更远,主goroutine也被阻塞了。
请注意,Go 程序在 main goroutine 结束时结束,因此如果您不尝试从 done_channel
读取,则不会发生这种死锁。
【讨论】:
以上是关于如何获取无缓冲通道中的元素数量的主要内容,如果未能解决你的问题,请参考以下文章