如何获取无缓冲通道中的元素数量

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 读取,则不会发生这种死锁。

【讨论】:

以上是关于如何获取无缓冲通道中的元素数量的主要内容,如果未能解决你的问题,请参考以下文章

如何获取指针数组中的元素数量?

如何获取分区中的元素数量? [复制]

如何定义通道缓冲区的最佳大小? [关闭]

如何获取所选选项的数量

如何获取数据堆栈上的元素数量?

如何获取columnA中不存在于ColumnB中的元素的数量