2015-07-21 21 views
6

無緩衝通道阻塞接收器,直到通道上有數據可用。我不清楚這種阻塞在同一個信道上有多個接收器(比如說使用goroutines時)的行爲。我相信,只要沒有在該頻道上發送數據,它們就會全部阻止。
但是,一旦我向該頻道發送單個值會發生什麼?哪個接收器/ goroutine會得到數據並因此解除阻塞?他們全部?第一個在線?隨機?單通道上有多個接收器。誰獲取數據?

回答

12

一個隨機(非確定性)的人會收到它。

+0

競爭條件?是否安全? –

+0

是的,這只是goroutine獲得元素的靈活性。 – inf

+4

我不會稱之爲「競賽條件」。該術語通常被定義爲表示由於不安全的併發訪問變量而導致的意外行爲。通道被設計爲可以同時安全地訪問,並且在無緩衝通道上的多個閱讀器沒有任何問題。 – JimB

4

默認情況下,goroutine通信是synchronousunbuffered:直到有一個接收器接受該值,發送纔會完成。必須有一個接收器準備好接收來自該頻道的數據,然後發送者可以直接將其傳送給接收器。

/接收操作,以便信道發送被阻塞,直到另一側已準備就緒:

1.上的信道塊A發送操作直至一個接收機是可用的相同的信道:如果沒有接收者的值在ch上,沒有其他值可以放在通道中。反過來說:ch當頻道不是空的時候不能發送新的值!所以發送操作將等到ch變爲可用。

2.一個信道的接收操作阻塞,直到一個發送器可用於相同的信道:如果信道中沒有值,則接收器阻塞。

這在下面的示例中被示出:

package main 
import "fmt" 

func main() { 
    ch1 := make(chan int) 
    go pump(ch1) // pump hangs 
    fmt.Println(<-ch1) // prints only 0 
} 

func pump(ch chan int) { 
    for i:= 0; ; i++ { 
     ch <- i 
    } 
} 

因爲沒有接收器的夠程掛起並打印所述第一數量。

要解決這個問題,我們需要定義一個新的goroutine,它從無限循環中的通道讀取數據。

func receive(ch chan int) { 
    for { 
     fmt.Println(<- ch) 
    } 
} 

然後在main()

func main() { 
    ch := make(chan int) 
    go pump(ch) 
    receive(ch) 
}