【问题标题】:can a message sent to channel be lost?发送到频道的消息会丢失吗?
【发布时间】:2016-03-31 13:09:12
【问题描述】:

问题在标题中。假设我有几个 goroutine(超过 100 个),所有这些最终都将数据发送给一个 chan(命名为 mychan := make(chan int))另一个 goroutine 在一个无休止的 for 循环中执行 <- mychan 是否可以,否则 chan 可能会丢失一些数据?我应该改用缓冲的chan吗?或者也许我要创建一个 chan 和一个“恶魔” goroutine 来为每个工作 goroutine 提取消息?

【问题讨论】:

  • 当有活动的 goroutines 仍在处理数据时,您的程序是否正在退出?这可能会使您发送的消息看起来丢失了。

标签: go concurrency goroutine


【解决方案1】:

如果某些内容已成功发送到通道中,那么不会,它不会在正确的工作环境中丢失(我的意思是,如果您正在篡改您的记忆或由于宇宙射线而发生位翻转,那么不要指望当然可以)。

ch <- x 返回时消息发送成功。否则,如果它发生恐慌,它并没有真正被发送,并且如果你没有恢复,那么你可以声称它已经丢失(但是,它会由于应用程序逻辑而丢失)。如果频道关闭,或者您的内存不足,就会发生恐慌。

同样,如果发送者以非阻塞模式(通过使用 select)进入通道,您的通道中应该有足够的缓冲区,因为消息可能会“丢失”(尽管是有意的)。例如signal.Notify 就是这样工作的:

包信号不会阻塞发送到 c:调用者必须确保 c 有足够的缓冲区空间来跟上预期的信号速率。

【讨论】:

    【解决方案2】:

    没有,它们不能被丢失。 P>

    虽然语言规范没有以任何方式强加频道任何特定的实现,则可以把它们看成semaphores保护是单一值(单个消息)或它们(用于缓冲的通道的阵列/列表)。

    的语义然后以这样的方式实施,一旦一个的goroutine想要发送消息给一个信道,它将尝试使用该信号来获取空闲数据槽,然后或者在succeds送有一个空闲时隙为它的消息或块 - 当不存在。一旦这样的时隙出现-有人已经接收现有的消息,发送成功并且发送够程变得畅通。 P>

    这是一个简单的解释,但我希望它可以让你在正确的思想。换句话说,在Go通道不像消息队列通常很高兴与丢失消息。 P>

    在一个侧面说明,我真的不知道,如果当它是关于在一些特定的状态下接收到恐慌收到您的邮件时会发生什么。 IOW我不能肯定是否转到保证了消息被在接收机中一个不幸的时刻恐慌的存在发送或不 P>

    哦,还有就是退出主够程的那个灰色地带(即一个运行main.main()功能):规范状态清除小于主够程不会等待任何其它够程退出时才能完成。所以,除非你以某种方式安排你所有的衍生够程的同步控制关机,我beleive他们可能会失去消息。在另一方面,在这种情况下,世界是反正折叠... P>

    【讨论】:

      【解决方案3】:

      消息不能丢失。不能发送。未定义 goroutines 执行的顺序。因此,您的无限 for 循环始终只能从一名工作人员接收,如果它不在主线程中,甚至可以休眠。为了确保您的队列以常规方式工作,您最好在“主”中明确接收每个工作人员的消息。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-12-05
        • 2023-03-07
        • 1970-01-01
        • 2018-12-23
        • 2021-03-24
        • 2019-09-03
        • 2021-10-28
        • 2015-05-26
        相关资源
        最近更新 更多