2010-10-17 16 views
9

I canali combinano la comunicazione, lo scambio di un valore, con la sincronizzazione, garantendo che due calcoli (goroutine) siano in uno stato noto.Come possiamo usare i canali in Go al posto del mutex?

Come è possibile utilizzare i canali in Google Go per eseguire la funzionalità di mutex?

package main 

import "sync" 

var global int = 0 
var m sync.Mutex 

func thread1(){ 
    m.Lock() 
    global = 1 
    m.Unlock() 
} 

func thread2(){ 
    m.Lock() 
    global = 2 
    m.Unlock() 
} 

func main(){ 
    go thread1() 
    go thread2() 
} 
+3

Questa domanda tipo di non coglie il punto. Dovresti chiederti "perché voglio un mutex, e come posso usare i canali, invece?" –

risposta

17

Un esempio di utilizzo di un canale come Mutex:

package main 

var global int = 0 
var c = make(chan int, 1) 

func thread1(){ 
    <-c // Grab the ticket 
    global = 1 
    c <- 1 // Give it back 
} 

func thread2(){ 
    <-c 
    global = 2 
    c <- 1 
} 

func main() { 
    c <- 1 // Put the initial value into the channel 
    go thread1() 
    go thread2() 
} 
+0

Grazie per la risposta MizardX. – Kevin

+0

Impressionante soluzione !! – HaltingState

+2

Mentre i canali forniscono una buona soluzione per i dati protetti, è una soluzione meno efficiente nel caso di uno scrittore e molti lettori. –

4

Se si dispone di un canale c che si inizializza con 1 punto in esso, allora si può "controllare" il "mutex", eliminando il valore dal canale (<-c). È possibile "rilasciarlo" aggiungendo il valore indietro (c <- 1).

Poiché l'operatore di estrazione da canale a) è atomico, e b) blocchi finché non c'è qualcosa da estrarre, funziona come un mutex, poiché se un thread di esecuzione lo ha già verificato, non ci sarà nulla in il canale, e quindi bloccherà fino a quando il thread che lo ha estratto restituisce un valore al canale per un altro thread da estrarre.

+0

Grazie Ambra. Possiamo avere l'esempio mostrato sopra implementato usando i canali invece del mutex? – Kevin

Problemi correlati