在chan中可以阻塞多少个写操作?

huangapple go评论103阅读模式
英文:

How many write operation can be blocked in chan

问题

我使用chan来进行goroutine的写入/读取操作,如果chan已满,写入的goroutine将被阻塞,直到另一个goroutine从chan中读取。

我知道在chan中有一个recvqsendq双向链表来记录被阻塞的goroutine。我的问题是,如果chan没有被读取,最多可以阻塞多少个goroutine?这是否取决于内存大小?

英文:

I use chan for goroutines to write/read, if the chan is full, the writing goroutines will be blocked until another goroutine read from the chan.

I know there is a recvq and sendq double linked list in chan to record blocked goroutines. My question is how many goroutines totally can be blocked if chan is not read? Does this depend on memory size?

答案1

得分: 2

只要您的应用程序可以适应内存并且可以运行,您就不会遇到通道等待队列的任何问题。

语言规范不限制通道的等待goroutine数量,因此没有实际限制。

运行时实现可能会将等待的goroutine限制在一个微不足道的高值(例如由于指针大小、整数计数器大小等),但要达到这样的实现限制,您将很快耗尽内存。

Goroutine是轻量级线程,但它们需要一小块内存。它们以大约1KB的小堆栈开始,因此即使您估计为1KB,如果您有一百万个goroutine,那至少需要1GB内存,如果您有十亿个goroutine,那就是1TB。而十亿远远不及例如int64的最大值。

在遇到特定实现的等待队列限制之前,您的CPU和Go运行时将在管理数十亿个goroutine方面遇到困难。

英文:

TLDR: as long as your app can fit into memory and can run, you won't have any problems with channel waiting queues.

The language spec does not limit the number of waiting goroutines for a channel, so there's no practical limit.

The runtime implementation might limit the waiting goroutines to an insignificant high value (e.g. due to pointer size, integer counter size or the likes), but to reach such an implementation limit, you would run out of memory much-much sooner.

Goroutines are lightweight threads, but they do require a small memory. They start with a small stack which is around a KB, so even if you estimate it to 1 KB, if you have a million goroutines, that's already 1 GB memory at least, and if you have a billion goroutines, that's 1 TB. And a billion is nowhere near to the max value of an int64 for example.

Your CPU and Go runtime would have trouble managing billions of goroutines earlier than running into implementation specific waiting queue limits.

答案2

得分: 1

是的,它取决于内存。根据文档中提到的通道长度,缓冲通道在通道满时被阻塞,并在向通道添加另一个值时解除阻塞。代码片段如下所示:

var sem = make(chan int, MaxOutstanding)

func handle(r *Request) {
    sem <- 1    // 等待活动队列排空。
    process(r)  // 可能需要很长时间。
    <-sem       // 完成;允许下一个请求运行。
}

func Serve(queue chan *Request) {
    for {
        req := <-queue
        go handle(req)  // 不等待 handle 完成。
    }
}

一旦有 MaxOutstanding 个处理程序正在执行 process,多余的处理程序将被阻塞,尝试发送到已满的通道缓冲区,直到现有的处理程序之一完成并从缓冲区接收。

英文:

Yes, it depends on the memory. It depends on the len of channel as mentioned in the docs, a buffered channel is blocked once the chan is full, and gets unblocked, when another value is added to the chan. channels

Code snippet from docs:

var sem = make(chan int, MaxOutstanding)

func handle(r *Request) {
    sem &lt;- 1    // Wait for active queue to drain.
    process(r)  // May take a long time.
    &lt;-sem       // Done; enable next request to run.
}

func Serve(queue chan *Request) {
    for {
        req := &lt;-queue
        go handle(req)  // Don&#39;t wait for handle to finish.
    }
}

Once MaxOutstanding handlers are executing process, any more will block trying to send into the filled channel buffer, until one of the existing handlers finishes and receives from the buffer.

答案3

得分: 1

如果通道没有被读取,那么所有的 goroutine 都会被阻塞。

英文:

> My question is how many goroutines totally can be blocked if chan is not read?

All of them.

huangapple
  • 本文由 发表于 2021年10月13日 17:22:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/69552878.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定