[英]Incomprehension of buffered channels described in the "Concurrency in Go" book
我閱讀了 Katherine Cox-Buday 所寫的“Go 中的並發”一書,但我不理解緩沖通道示例的評論。
作者說:
if a goroutine making writes to a channel has knowledge of how many writes it will make,
it can be useful to create a buffered channel whose capacity is the number of writes to be made
聽起來很清楚,但例子令人困惑。
var stdoutBuff bytes.Buffer // <1>
defer stdoutBuff.WriteTo(os.Stdout) // <2>
intStream := make(chan int, 4) // <3>
go func() {
defer close(intStream)
defer fmt.Fprintln(&stdoutBuff, "Producer Done.")
for i := 0; i < 5; i++ {
fmt.Fprintf(&stdoutBuff, "Sending: %d\n", i)
intStream <- i
}
}()
for integer := range intStream {
fmt.Fprintf(&stdoutBuff, "Received %v.\n", integer)
}
帶有注釋<3>
的行有以下解釋:
Here we create a buffered channel with a capacity of one.
有 4 個,而不是 1 個。是不是搞錯了?
chanOwner := func() <-chan int {
resultStream := make(chan int, 5) // <1>
go func() { // <2>
defer close(resultStream) // <3>
for i := 0; i <= 5; i++ {
resultStream <- i
}
}()
return resultStream // <4>
}
標記為<1>
的行具有以下注釋:
Since we know we will produce six results, we create a buffered channel of five
so that the goroutine can complete as quickly as possible.
我完全不明白這個評論。 Goroutine 會被阻塞,因為通道有 5 條消息的容量,會產生 6 條消息,所以它會等到接收者收到第一條消息。
因為我們知道我們將產生六個結果,所以我們創建了一個 5 個緩沖通道,以便 goroutine 可以盡快完成。
你是正確的,goroutine 將阻塞直到收到一個值。
創建一個容量比要發送的值數量少一的通道是沒有意義的。 如果通道容量等於或大於值的數量,則可以消除 goroutine:
chanOwner := func() <-chan int {
resultStream := make(chan int, 6)
for i := 0; i < cap(resultStream); i++ {
resultStream <- i
}
close(resultStream)
return resultStream
}()
或者通過消除匿名 function 來實現:
chanOwner := make(chan int, 6)
for i := 0; i < cap(chanOwner); i++ {
resultStream <- i
}
close(chanOwner)
是的,聽起來這本書需要一個更好的編輯器!
通道容量確實表示為make
的第二個參數:
intStream := make(chan int, 4) // buffered-channel of capacity 4 (not 1!)
如果沒有在通道上進行讀取 - 那么寫入 goroutine 將寫入 5 次到緩沖通道(容量為 5)而沒有問題(即沒有阻塞)。 第 6 次寫入確實會阻塞 - 在緩沖區擁塞減少之前,goroutine 不會返回。
如果其他一些 goroutine 確實從通道中讀取了 - 甚至只是一次 - 然后緩沖區被釋放並且 writer goroutine 將能夠完成最終的寫入。
有 4 個,而不是 1 個。是不是搞錯了?
這似乎是一個錯字。 正如文檔中make
指出的,第二個參數是通道容量:
通道:通道的緩沖區被初始化為指定的緩沖區容量。 如果為零或省略大小,則通道是無緩沖的。
因此make(chan int, 4)
是容量為 4 的 chan。
Goroutine 會被阻塞,因為通道有 5 條消息的容量,會產生 6 條消息,所以它會等到接收者收到第一條消息。
正確,聲明的 chan 容量為 5,如果沒有接收器,第六個也是最后一個發送操作確實會阻塞,因為通道緩沖區已滿。
假設各方都是善意的,這本書可能錯過了一輪校對。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.