1
janxin 2018-03-15 07:28:51 +08:00
看需求...
|
2
harry890829 2018-03-15 08:50:56 +08:00
搭车问下,我这边想用下协程池,是不是可以利用 chan 的阻塞机制?假设我 10 个协程都在等待 chan,chan 有内容自然就被协程读取了
|
3
snail1988 2018-03-15 09:22:49 +08:00
协程就没必要池了吧,开销很低
|
4
Reset 2018-03-15 10:09:18 +08:00
@harry890829 10 个 goroutine 等待一个同一个 chan? 这样只会被某一个 goroutine 执行的
|
5
harry890829 2018-03-15 10:11:35 +08:00
@Reset #4 是啊,这就是目的啊,生产者消费者嘛,我生产者不停的往 chan 加载,消费者 10 个 goroutine 等待 chan,如果 chan 有内容,是不是就被某一个 goroutine 读取,如果 chan 为空,则 goroutine 则进入阻塞状态?
|
6
panyanyany 2018-03-15 10:16:24 +08:00
@harry890829 #5 那你最好是用带缓冲的 chan,如果不带缓冲的话,你的其他 9 个 goroutine 会被堵住,写不进去。
|
8
monnand 2018-03-15 10:35:59 +08:00 via Android
不带缓存。这样方便收发双方同步。
|
9
missdeer 2018-03-15 10:41:09 +08:00
@harry890829 就是这样
|
10
Reset 2018-03-15 10:41:25 +08:00
@harry890829 那你为什么不直接用一个 roroutine 接受 chan, 读取成功后在直接 起一个 goroutine 也可以
for { e := <- ch go some_func(e) } |
11
harry890829 2018-03-15 11:01:43 +08:00
@snail1988 #3 还是弄个池吧,我这边外部消息进来不可控,担心量大的时候给冲垮,主要是考虑到协程中还会需要进行数据库、文件等操作,协程可能本身没问题,但是协程量过大把数据库拖垮了就 sb 了
@panyanyany #6 现在准备用缓冲的 chan 来操作 @Reset #10 恩恩,大致是这个意思,不过我需要控制 goroutine 的总量,goroutine 中会包含数据库操作,担心后来的操作有影响 |
12
Reset 2018-03-15 12:04:42 +08:00
@harry890829 那你也可以使用带容量的 channel 然后根据 len(ch) 加上 sync.WaitGroup 来实现, 不过你的方案如果能行的话效率应该是最高的
虽然带容量, 在 ch 满了之后会依然是阻塞的, 会导致 producer 不能继续, 之前做一个服务的时候有种场景 「 producer 可以不断的生产消息, 但是 consumer 需要限制消费速度」 channel 这个时候并是不很适用, 后来使用 slice 加 atomic 做的队列实现的 |
13
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) }() } } }() |
14
JamesRuan 2018-03-15 13:24:43 +08:00
如上。
带 buffer 的 channel 天然就是一个 pool。 |
15
harry890829 2018-03-15 15:33:15 +08:00
|
17
JamesRuan 2018-03-17 10:36:54 +08:00
@admirez 这个就是需求呀。
buffer 不是为了不堵住的,而是为了控制堵住数量的。独占的话 buffer 就是 0,允许一个等待,buffer 就是 1。 |
18
JamesRuan 2018-03-17 10:38:37 +08:00
@harry890829 chan chan 是好东西,外层 chan 带 buffer 排队,内层 chan 同步传具体数据。
|