簡體   English   中英

Go 緩沖和非緩沖通道故障

[英]Go trouble with buffered and unbuffered channels

我對 Go 中緩沖通道和非緩沖通道之間的區別有點困惑。 例如,下面的代碼執行良好:

package main

import "fmt"

func main() {
    messages := make(chan string)
    go func() { messages <- "ping" }()
    msg := <-messages
    fmt.Println(msg)
}

另一方面,當我將"ping"傳遞給常規 function 中的消息時,會出現死鎖。

package main

import "fmt"

func main() {
    messages := make(chan string)
    func() { messages <- "ping" }()
    msg := <-messages
    fmt.Println(msg)
}

最后,當我使用緩沖通道時,這是固定的,就像這樣

package main

import "fmt"

func main() {
    messages := make(chan string, 1)
    func() { messages <- "ping" }()
    msg := <-messages
    fmt.Println(msg)
}

我很困惑為什么第二個案例失敗了。 Go By Example 說

默認情況下,通道是無緩沖的,這意味着如果有相應的接收 (<- chan) 准備好接收發送的值,它們將只接受發送 (chan <-)。 緩沖通道接受有限數量的值,而這些值沒有相應的接收器。

在這三種情況下,不是msg messages器嗎?

如果未讀取無緩沖通道,則它們會阻塞。 緩沖通道在達到容量之前不會阻塞。

您的第一個示例實際上啟動了一個單獨的 go 例程,該例程執行 function 嘗試將“ping”寫入消息通道。 它將阻塞,直到從消息通道讀取的語句執行。 由於 function 位於單獨的 goroutine 上,因此從消息通道讀取的語句能夠被命中。

您的第二個示例聲明並調用 function 嘗試寫入消息通道,但該通道永遠不會准備好寫入,因為您正在同一個主執行線程上執行。 從消息通道讀取的語句永遠不會命中,因為您在寫入通道時被阻止。

第三個例子,通道被緩沖並且可以被寫入,因為它可以在阻塞之前接受 1 個值。

在第一個示例中,嵌套的 function 從另一個 goroutine 調用。 function 開始運行並阻塞等待寫入通道。 主 goroutine 也運行,並從通道讀取,釋放第二個 goroutine 中的塊。

在第二個例子中,嵌套的 function 被 main 調用,main 等待它返回。 由於通道沒有緩沖,寫操作阻塞,這意味着主協程被阻塞,沒有其他協程,所以死鎖。

在第三個示例中,通道被緩沖,因此第一次寫入不會阻塞。

您可能已經瀏覽了那里的一個關鍵詞:“如果有相應的接收 (<-chan)准備好接收發送的值”。

在您的第一個示例中,接收器與發送器同時運行,因此當發送器發送時,接收器此時已准備好接收。 在第二個示例中,它們沒有同時運行,因此當發送方發送時,沒有准備好接收(因為接收操作在匿名 function 返回之前不會運行),並且發送阻塞。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM