2015-07-21 7 views
6

I canali non bufferizzati bloccano i ricevitori finché i dati non sono disponibili sul canale. Non mi è chiaro come si comporta questo blocco con più ricevitori sullo stesso canale (ad esempio quando si usano le goroutine). Sono sicuro che tutti bloccherebbero finché non ci saranno dati inviati su quel canale.
Ma cosa succede dopo aver inviato un singolo valore a quel canale? Quale ricevitore/goroutine otterrà i dati e quindi sbloccherà? Tutti loro? Il primo in fila? Casuale?Più ricevitori su un singolo canale. Chi ottiene i dati?

risposta

12

Uno singolo casuale (non deterministico) lo riceverà.

+0

condizione Race? È sicuro farlo? –

+0

Sì, certo, è proprio audace quale goroutine ottiene l'elemento. – inf

+4

Non lo chiamerei "race condition". Questo termine è convenzionalmente definito per indicare un comportamento indesiderato a causa di un accesso concorrente non sicuro di una variabile. I canali sono progettati per l'accesso sicuro in contemporanea e non c'è nulla di sbagliato con più lettori su un canale non bufferizzato. – JimB

4

Per impostazione predefinita, la comunicazione di goroutine è synchronous e unbuffered: le mandate non vengono completate finché un destinatario non accetta il valore. Ci deve essere un ricevitore pronto a ricevere dati dal canale e quindi il mittente può consegnarlo direttamente al ricevitore.

invio Così canale/ricezione operazioni di bloccare fino a quando l'altro lato è pronto:

1. Un'operazione di invio su un blocchi di canale fino a quando un ricevitore è disponibile per lo stesso canale: se non c'è destinatario per il valore su ch, nessun altro valore può essere inserito nel canale. E viceversa: nessun nuovo valore può essere inviato in ch quando il canale non è vuoto! Quindi l'operazione di invio attenderà fino a quando ch sarà nuovamente disponibile.

2. Un'operazione di ricezione per un blocco di canali finché non è disponibile un mittente per lo stesso canale: se non c'è alcun valore nel canale, il ricevitore si blocca.

Ciò è illustrato nel seguente esempio:

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

Poiché non c'è ricevitore si blocca goroutine e stampare solo il primo numero.

Per risolvere questo problema, è necessario definire una nuova goroutine che legge dal canale in un ciclo infinito.

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

Poi nel main():

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