【问题标题】:Can unbuffered channel be used to receive signal?可以使用无缓冲通道接收信号吗?
【发布时间】:2021-10-06 03:58:01
【问题描述】:

在下面的代码中:

package main

import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
)

func main() {

    sigs := make(chan os.Signal, 1)
    done := make(chan bool, 1)

    signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

    go func() {
        sig := <-sigs
        fmt.Println()
        fmt.Println(sig)
        done <- true
    }()

    fmt.Println("awaiting signal")
    <-done
    fmt.Println("exiting")
}

大小为一个缓冲通道用于接收信号。

无缓冲通道提供交付保证。

设置一个缓冲通道提供延迟保证


我们可以在这种情况下使用无缓冲通道吗? sigs := make(chan os.Signal)

【问题讨论】:

标签: go goroutine


【解决方案1】:

来自signal.Notify documentation

包信号不会阻塞发送到 c:调用者必须确保 c 有足够的缓冲区空间来跟上预期的信号速率。对于仅用于通知一个信号值的通道,大小为 1 的缓冲区就足够了。

所以,回答你的问题:

无缓冲通道提供交付保证。

这是不正确的。只有了解发送方和接收方的行为,才能保证送达。

在这种情况下,发送者是非阻塞的。因此,如果接收方没有等待信号,则消息将被丢弃。

设置一个缓冲通道提供延迟保证

频道中没有“延迟”。缓冲区就是通道中可以存储多少项。

在这种情况下我们可以使用无缓冲通道吗?

代码将可能工作,但不能保证工作。问题是你不知道这行代码什么时候执行:

sig := <-sigs

任何在signal.Notify 之后但在&lt;-sigs 之前到达的信号都将被丢弃(如果通道没有缓冲)。请记住,signal.Notify 是非阻塞的——这只是意味着它将放弃而不是等待。

如果您不想丢弃信号,请使用缓冲通道。

当然,这种情况不太可能发生。但这在技术上是可行的。

【讨论】:

  • 为了您的观点....“在signal.Notify 之后但在&lt;-sigs 之前到达的任何信号都将被丢弃(如果通道没有缓冲)。”它是否正确?因为信号不会被丢弃,但发送方将被阻塞在无缓冲通道上
  • Unbuffered channels provide guarantee of delivery. 意味着发送者被阻塞,直到接收者收到数据。这保证了交货。在我们退出程序之前,数据永远不会被丢弃。
  • @overexchange:根据文档,信号处理程序不会阻塞。由于它不会阻塞,因此如果接收器未准备好,它可以做其他事情。在这种情况下,信号被丢弃。如果要保证交付,则必须使用缓冲通道。
猜你喜欢
  • 2020-09-30
  • 1970-01-01
  • 1970-01-01
  • 2017-02-08
  • 1970-01-01
  • 2012-10-17
  • 2014-01-30
相关资源
最近更新 更多