2015-07-21 4 views
6

Ungepufferte Kanäle blockieren Empfänger, bis Daten auf dem Kanal verfügbar sind. Es ist mir nicht klar, wie sich dieses Blocking mit mehreren Empfängern auf dem gleichen Kanal verhält (sagen wir mal bei der Verwendung von Goroutines). Ich bin sicher, sie würden alle blockieren, solange keine Daten über diesen Kanal gesendet werden.
Aber was passiert, nachdem ich einen einzelnen Wert an diesen Kanal gesendet habe? Welcher Empfänger/goroutine wird die Daten bekommen und somit entsperren? Alle von ihnen? Der erste in der Reihe? Zufällig?Mehrere Empfänger auf einem einzelnen Kanal. Wer bekommt die Daten?

Antwort

12

Ein einzelnes zufälliges (nicht deterministisches) wird es erhalten.

+0

Race Condition? Ist es sicher zu tun? –

+0

Ja sicher, es ist nur rassig, welche Goroutine das Element bekommt. – inf

+4

Ich würde es nicht eine "Race Condition" nennen. Dieser Begriff ist konventionell definiert, um unbeabsichtigtes Verhalten aufgrund eines unsicheren gleichzeitigen Zugriffs einer Variablen anzuzeigen. Kanäle sind so ausgelegt, dass sie gleichzeitig sicher zugänglich sind, und es gibt nichts Falsches an mehreren Lesegeräten auf einem ungepufferten Kanal. – JimB

4

Standardmäßig ist die Goroutinerkommunikation synchronous und unbuffered: Senden wird erst abgeschlossen, wenn ein Empfänger den Wert akzeptiert. Es muss ein Empfänger bereit sein, um Daten von dem Kanal zu empfangen, und der Sender kann ihn dann direkt an den Empfänger übergeben.

So Kanal-Sende-/Empfangsvorgänge blockiert, bis die andere Seite ist bereit:

1. Ein Sendevorgang auf einem Kanal blockiert, bis ein Empfänger für den gleichen Kanal verfügbar ist: wenn es kein Empfänger für den Wert unter ch kann kein anderer Wert in den Kanal eingegeben werden. Und umgekehrt: In ch kann kein neuer Wert gesendet werden, wenn der Kanal nicht leer ist! Der Sendevorgang wartet also, bis ch wieder verfügbar wird.

2. Ein Empfangsvorgang für einen Kanal blockiert, bis ein Sender für denselben Kanal verfügbar ist: Wenn kein Wert im Kanal vorhanden ist, blockiert der Empfänger.

Dies wird im folgenden Beispiel veranschaulicht:

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

Da es keine Empfänger nur die erste Zahl goroutine hängt und Druck ist.

Um dies zu umgehen, müssen wir eine neue goroutine definieren, die aus dem Kanal in einer Endlosschleife liest.

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

Dann in main():

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