一般来说 chan 推荐用带缓冲的还是不带缓冲?

2018-03-15 07:26:27 +08:00
 admirez
1950 次点击
所在节点    Go 编程语言
18 条回复
janxin
2018-03-15 07:28:51 +08:00
看需求...
harry890829
2018-03-15 08:50:56 +08:00
搭车问下,我这边想用下协程池,是不是可以利用 chan 的阻塞机制?假设我 10 个协程都在等待 chan,chan 有内容自然就被协程读取了
snail1988
2018-03-15 09:22:49 +08:00
协程就没必要池了吧,开销很低
Reset
2018-03-15 10:09:18 +08:00
@harry890829 10 个 goroutine 等待一个同一个 chan? 这样只会被某一个 goroutine 执行的
harry890829
2018-03-15 10:11:35 +08:00
@Reset #4 是啊,这就是目的啊,生产者消费者嘛,我生产者不停的往 chan 加载,消费者 10 个 goroutine 等待 chan,如果 chan 有内容,是不是就被某一个 goroutine 读取,如果 chan 为空,则 goroutine 则进入阻塞状态?
panyanyany
2018-03-15 10:16:24 +08:00
@harry890829 #5 那你最好是用带缓冲的 chan,如果不带缓冲的话,你的其他 9 个 goroutine 会被堵住,写不进去。
zzn
2018-03-15 10:18:43 +08:00
@snail1988 开销是很低,但池化的一个好处是不会瞬间创建太多协程导致系统资源不足
monnand
2018-03-15 10:35:59 +08:00
不带缓存。这样方便收发双方同步。
missdeer
2018-03-15 10:41:09 +08:00
@harry890829 就是这样
Reset
2018-03-15 10:41:25 +08:00
@harry890829 那你为什么不直接用一个 roroutine 接受 chan, 读取成功后在直接 起一个 goroutine 也可以

for {
e := <- ch
go some_func(e)
}
harry890829
2018-03-15 11:01:43 +08:00
@snail1988 #3 还是弄个池吧,我这边外部消息进来不可控,担心量大的时候给冲垮,主要是考虑到协程中还会需要进行数据库、文件等操作,协程可能本身没问题,但是协程量过大把数据库拖垮了就 sb 了
@panyanyany #6 现在准备用缓冲的 chan 来操作
@Reset #10 恩恩,大致是这个意思,不过我需要控制 goroutine 的总量,goroutine 中会包含数据库操作,担心后来的操作有影响
Reset
2018-03-15 12:04:42 +08:00
@harry890829 那你也可以使用带容量的 channel 然后根据 len(ch) 加上 sync.WaitGroup 来实现, 不过你的方案如果能行的话效率应该是最高的
虽然带容量, 在 ch 满了之后会依然是阻塞的, 会导致 producer 不能继续,
之前做一个服务的时候有种场景 「 producer 可以不断的生产消息, 但是 consumer 需要限制消费速度」 channel 这个时候并是不很适用, 后来使用 slice 加 atomic 做的队列实现的
JamesRuan
2018-03-15 13:22:55 +08:00
pool := make(chan chan Work, poolSize)
stop := make(chan struct{})
go func() {
for {
waitWork := make(chan work)
select {
case <-stop:
return
case pool <- waitWork:
go func() {
doWork(<-waitWork)
close(waitWork)
}()
}
}
}()
JamesRuan
2018-03-15 13:24:43 +08:00
如上。
带 buffer 的 channel 天然就是一个 pool。
harry890829
2018-03-15 15:33:15 +08:00
@Reset #12 恩恩,我生产者本身是 kafka 的消费者,所以阻塞的话应该问题不大,到时候我压测一下,结合生产数据量算算
@JamesRuan #13 pool 是 chan chan 结构?我还没用过这东西,晚点研究研究
admirez
2018-03-15 20:20:27 +08:00
@JamesRuan 可是 buffer 满了的话 channel 就堵住了
JamesRuan
2018-03-17 10:36:54 +08:00
@admirez 这个就是需求呀。
buffer 不是为了不堵住的,而是为了控制堵住数量的。独占的话 buffer 就是 0,允许一个等待,buffer 就是 1。
JamesRuan
2018-03-17 10:38:37 +08:00
@harry890829 chan chan 是好东西,外层 chan 带 buffer 排队,内层 chan 同步传具体数据。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/438160

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX