Golang Go语言中一般来说 chan 推荐用带缓冲的还是不带缓冲?

发布于 1周前 作者 gougou168 来自 Go语言

null
Golang Go语言中一般来说 chan 推荐用带缓冲的还是不带缓冲?

19 回复

看需求…

更多关于Golang Go语言中一般来说 chan 推荐用带缓冲的还是不带缓冲?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


搭车问下,我这边想用下协程池,是不是可以利用 chan 的阻塞机制?假设我 10 个协程都在等待 chan,chan 有内容自然就被协程读取了

协程就没必要池了吧,开销很低

10 个 goroutine 等待一个同一个 chan? 这样只会被某一个 goroutine 执行的

#4 是啊,这就是目的啊,生产者消费者嘛,我生产者不停的往 chan 加载,消费者 10 个 goroutine 等待 chan,如果 chan 有内容,是不是就被某一个 goroutine 读取,如果 chan 为空,则 goroutine 则进入阻塞状态?

#5 那你最好是用带缓冲的 chan,如果不带缓冲的话,你的其他 9 个 goroutine 会被堵住,写不进去。

开销是很低,但池化的一个好处是不会瞬间创建太多协程导致系统资源不足

不带缓存。这样方便收发双方同步。

那你为什么不直接用一个 roroutine 接受 chan, 读取成功后在直接 起一个 goroutine 也可以

for {
e := <- ch
go some_func(e)
}

#3 还是弄个池吧,我这边外部消息进来不可控,担心量大的时候给冲垮,主要是考虑到协程中还会需要进行数据库、文件等操作,协程可能本身没问题,但是协程量过大把数据库拖垮了就 sb 了
#6 现在准备用缓冲的 chan 来操作
#10 恩恩,大致是这个意思,不过我需要控制 goroutine 的总量,goroutine 中会包含数据库操作,担心后来的操作有影响

那你也可以使用带容量的 channel 然后根据 len(ch) 加上 sync.WaitGroup 来实现, 不过你的方案如果能行的话效率应该是最高的
虽然带容量, 在 ch 满了之后会依然是阻塞的, 会导致 producer 不能继续,
之前做一个服务的时候有种场景 「 producer 可以不断的生产消息, 但是 consumer 需要限制消费速度」 channel 这个时候并是不很适用, 后来使用 slice 加 atomic 做的队列实现的

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

如上。
带 buffer 的 channel 天然就是一个 pool。

#12 恩恩,我生产者本身是 kafka 的消费者,所以阻塞的话应该问题不大,到时候我压测一下,结合生产数据量算算
#13 pool 是 chan chan 结构?我还没用过这东西,晚点研究研究

可是 buffer 满了的话 channel 就堵住了

这个就是需求呀。
buffer 不是为了不堵住的,而是为了控制堵住数量的。独占的话 buffer 就是 0,允许一个等待,buffer 就是 1。

chan chan 是好东西,外层 chan 带 buffer 排队,内层 chan 同步传具体数据。

在Golang(Go语言)中,对于chan(通道)的选择,是使用带缓冲的还是不带缓冲的,这取决于具体的应用场景和需求。

不带缓冲的通道(unbuffered channel)在没有数据可读或可写时会阻塞。这种特性使得它在同步多个goroutine时非常有用,可以确保数据的一致性和顺序性。在需要严格控制数据流动和时序的场景下,不带缓冲的通道通常是更好的选择。

带缓冲的通道(buffered channel)则提供了一个缓冲区,可以在缓冲区未满时发送数据而不阻塞,或在缓冲区未空时接收数据而不阻塞。这可以提高程序的并发性能,减少goroutine之间的等待时间。然而,使用带缓冲的通道时需要谨慎,因为不当的缓冲区大小可能会导致数据丢失、资源竞争或死锁等问题。

因此,推荐的做法是根据实际需求来选择:

  • 如果需要严格的同步和数据一致性,或者数据流动时序非常重要,那么不带缓冲的通道是更好的选择。
  • 如果需要提高并发性能,且能够合理设置缓冲区大小以避免潜在问题,那么带缓冲的通道可能更适合。

总之,在选择带缓冲还是不带缓冲的通道时,应权衡同步需求、性能要求和潜在风险,做出最适合具体应用场景的选择。

回到顶部