可以使用非缓冲通道来接收信号吗?

huangapple go评论90阅读模式
英文:

Can unbuffered channel be used to receive signal?

问题

在下面的代码中:

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")
}

在接收信号的地方使用了一个大小为1的缓冲通道。

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

大小为1的缓冲通道提供了延迟的保证。


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

英文:

In the below code:

package main

import (
    &quot;fmt&quot;
    &quot;os&quot;
    &quot;os/signal&quot;
    &quot;syscall&quot;
)

func main() {

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

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

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

    fmt.Println(&quot;awaiting signal&quot;)
    &lt;-done
    fmt.Println(&quot;exiting&quot;)
}

Size one buffered channel is used for receiving signal.

Unbuffered channels provide guarantee of delivery.

Size one buffered channel provides delayed guarantee


Can we use unbuffered channel in this scenario? sigs := make(chan os.Signal)

答案1

得分: 15

signal.Notify文档中可以得知:

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

所以,回答你的问题:

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

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

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

> 大小为1的缓冲通道提供延迟保证。

通道中没有“延迟”。缓冲区只是指通道中可以存储的项目数量。

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

代码可能会工作,但不能保证。问题在于你不知道这行代码何时会被执行:

sig := &lt;-sigs

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

如果你不希望信号被丢弃,请使用带缓冲的通道。

这种情况不太可能发生,但从技术上讲是可能的。

英文:

From the signal.Notify documentation

> Package signal will not block sending to c: the caller must ensure that c has sufficient buffer space to keep up with the expected signal rate. For a channel used for notification of just one signal value, a buffer of size 1 is sufficient.

So, to answer your question:

> Unbuffered channels provide guarantee of delivery.

This is incorrect. Delivery can only be guaranteed if you know both the behavior of the sender and receiver.

In this case, the sender is non-blocking. So if the receiver is not waiting for a signal, the message will be discarded.

> Size one buffered channel provides delayed guarantee

There is no “delay” in a channel. The buffer is just how many items can be stored in the channel.

> Can we use unbuffered channel in this scenario?

The code will probably work, but it is not guaranteed to work. The problem is that you don’t know when this line will get executed:

sig := &lt;-sigs

Any signal which arrives after signal.Notify but before &lt;-sigs will get discarded (if the channel is unbuffered). Remember that signal.Notify is non-blocking—this just means that it will give up instead of wait.

If you don’t want signals to get discarded, use a buffered channel.

This scenario is unlikely, sure. But it is technically possible.

huangapple
  • 本文由 发表于 2021年7月30日 23:49:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/68593779.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定