【问题标题】:Can data coming from different channels into select statement get ignored?来自不同渠道的数据进入 select 语句会被忽略吗?
【发布时间】:2015-05-07 18:04:26
【问题描述】:

如果没有在 select 语句中的正确时刻捕获通过 golang 中的通道进入的数据,是否有可能被忽略?

例如,假设有这样的选择语句:

for {
    select {
    case <-timer.C:
        //block A
    default:
        // block B takes 2 seconds.
    }
}

如果定时器在块 B 运行时结束,块 A 是否仍会在循环的下一次迭代中运行,还是通道的传入数据会丢失?

【问题讨论】:

  • 在发送端,如果它是一个有空间的缓冲通道,那么数据就会被缓冲。否则,它取决于写入器是否阻塞,以及它是否不阻塞,是否重试或继续并丢弃数据。删除/忽略数据的另一种方法是让读取器退出而不读取缓冲项。

标签: go channel


【解决方案1】:

当定时器到时,它会在C上发送当前时间。如果当时没有人从C读取,发送会阻塞,所以它会一直等到接收到值。在这种情况下,它将等到循环的下一次迭代。

通道被设计为一种同步机制,因此它们不需要读取器和写入器已经同步。

【讨论】:

  • 小改正,time.NewTimer 使用缓冲通道,使其无法阻塞。它将时间写入缓冲区,然后有人读取它,或者,如果不再引用计时器和通道,它们最终会被垃圾收集。
  • 相关,time.NewTicker 也使用缓冲区大小为 1 的通道并进行非阻塞发送。如果阅读器落后(如果缓冲区已满,则下一个滴答被丢弃),它被记录为丢弃滴答。
  • 感谢您的澄清。我懒得看源码看通道是否被缓冲了。
  • 这是一个次要的实现细节,你的答案仍然是正确的。
猜你喜欢
  • 2020-06-18
  • 2017-09-22
  • 2019-02-16
  • 1970-01-01
  • 2013-07-06
  • 1970-01-01
  • 2015-08-13
  • 2014-03-04
  • 2016-02-09
相关资源
最近更新 更多