多个生产者,一个消费者:所有goroutine都在睡眠中-死锁

多个生产者,一个消费者:所有goroutine都在睡眠中-死锁,第1张

多个生产者,一个消费者:所有goroutine都在睡眠中-死锁

鉴于您在一个频道上确实有多个作者,因此您会遇到一些挑战,因为在Go中执行此 *** 作的简单方法通常是在一个频道上拥有一个作者,然后让该作者关闭频道。发送最后一个数据时的通道

func produce(... args including channel) {    defer close(ch)    for stuff_to_produce {        ch <- item    }}

这种模式具有很好的特性,无论您如何退出

produce
,通道都会关闭,从而指示生产已结束。

您没有使用这种模式,而是向多个goroutine传递了一个通道,每个goroutine都可以发送 一条
消息,因此您需要移动

close
(当然,也可以使用其他模式)。表达所需模式的最简单方法是:

func overall_produce(... args including channel ...) {    var pg sync.WaitGroup    defer close(ch)    for stuff_to_produce {        pg.Add(1)        go produceInParallel(ch, &pg) // add more args if appropriate    }    pg.Wait()}

pg
计数器累计活跃的生产者。每个调用都必须使用
pg.Done()
来表明已完成
ch
。总制片人现在等待他们全部完成,那么
关闭的道路上走出通道。

(如果将内部

produceInParallel
函数编写为闭包,则无需显式传递
ch
并传递
pg
给它。也可以将其编写
overallProducer
为闭包。)

请注意,单个使用者的循环可能最好使用以下

for ... range
结构来表示:

func receive(msg <-chan message, wg *sync.WaitGroup) {    for m := range msg {        fmt.Println("Received:", m)    }    wg.Done()}

(您提到了

select
向循环添加a的意图,以便在消息尚未准备好时可以执行其他一些计算。如果无法将该代码分解为独立的goroutine,则实际上您将需要更高级的
m,ok := <-msg
构造。)

还要注意,

wg
for
receive
(取决于您构造其他事物的方式可能是不必要
pg
的)与生产者的等待组非常独立。诚然,按照书面说明,只有在所有生产者都完成之后才能完成消费者的工作,但我们希望独立等待生产者完成,以便我们可以关闭整体生产者包装中的渠道。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5013035.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-14
下一篇 2022-11-14

发表评论

登录后才能评论

评论列表(0条)

保存