【问题标题】:golang channel behaviour with for loops带有 for 循环的 golang 通道行为
【发布时间】:2018-02-13 01:17:01
【问题描述】:

我很好奇通道的行为以及它们与循环相关的工作方式。假设我有以下代码:

消费者

tick := time.Tick(time.Duration(2) * time.Second)
for {
    select {
    case <-tick:
        p.channel <-true
    }
}

我有一个 goroutine,它具有以下内容:

处理器

for {
    select {
    case canProcess := <-p.channel:
        // synchronous process that takes longer than 2 seconds
    case <-p.stop:
        return
    }
}

Consumer 推送到频道的速度快于 Processor 完成其同步过程时会发生什么?

它们是堆积起来等待处理器完成还是跳过“节拍”?

如果它们堆积起来,是否存在内存泄漏的可能性?

我知道我可以将同步过程放在 goroutine 中,但这真的是为了了解通道的行为方式。 (即我的示例有 2 秒的滴答声,但不是必须的)。

【问题讨论】:

  • 为了记录,单例选择语句从来没有用处。只需直接从频道接收,它在机械上与只有一个案例(并且没有默认值)的选择相同。此外,time.Tick 的文档注释说它是 time.NewTicker 的便利包装,time.Ticker 的文档注释它会丢弃滴答声以弥补慢速接收器。所以如果你的处理器很慢,ticker 会跳过 tick,直到你的消费者循环准备好再次接收 tick。 golang.org/pkg/time/#Ticker

标签: go goroutine


【解决方案1】:

select只会在下一次调用。如果上一个case对应的代码已经完成,打勾,
你仍然可以通过指定通道的大小来获得一些杠杆,即 channel := make(chan bool,10)

见下文:

func main() {

    channel := make(chan bool, 10)
    go func() {
        tick := time.Tick(time.Duration(1) * time.Second)
        for {
            select {
            case <-tick:
                fmt.Printf("Producer: TICK %v\n", time.Now())
                channel <- true
                }
        }
    }()

    for {
        select {
        case canProcess := <-channel:
            time.Sleep(3*  time.Second)
            fmt.Printf("Consumer: Completed : %v\n")
            fmt.Printf("%v\n", canProcess)
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    • 2013-10-08
    • 1970-01-01
    • 2021-12-07
    • 1970-01-01
    相关资源
    最近更新 更多