2015-08-12 10 views
5

ho definita una variabile (r.something) all'interno di un oggettoÈ richiesta la sincronizzazione?

func (r *Runner) init() { 
    r.something = make(map[string]int) 
    r.something["a"]=1 

    go r.goroutine() 
} 

mentre r.goroutine utilizza valore memorizzato in r.something senza sincronizzazione. Nessun altro leggerà/scriverà questo valore eccetto r.goroutine()

È sicuro fare a meno della sincronizzazione?

In altre parole: Voglio riutilizzare alcune variabili da una goroutine inizializzate altrove prima dell'inizio di goroutine. È sicuro?

Domanda aggiuntiva: Dopo aver terminato r.groutine(), desidero poter utilizzare r.something da qualche altra parte (senza sovrapposizioni di lettura/scrittura con altre goroutine). È sicuro?

risposta

5

Naturalmente questo è sicuro, altrimenti programmare in Go potrebbe essere un incubo (o almeno molto meno piacevole). The Go Memory Model è un pezzo interessante da leggere.

La creazione di routine è un punto di sincronizzazione. C'è un esempio molto simile al vostro:

var a string 

func f() { 
    print(a) 
} 

func hello() { 
    a = "hello, world" 
    go f() 
} 

con il seguente commento:

chiamando ciao stamperà "ciao, mondo", ad un certo punto nel futuro (forse dopo ciao è tornato).

Questo perché:

La dichiarazione go che inizia una nuova goroutine accade prima l'esecuzione del goroutine inizia.

La parola prima è cruciale poiché implica la creazione di routine (in un thread) deve essere sincronizzato con il suo inizio (eventualmente in altro thread), quindi scrive a un deve essere visibile dalla nuova routine .

+0

Ha assolutamente senso! Grazie a @tomasz – let4be

3

Se non c'è una situazione in cui sovrapposizione di lettura e scrittura operazioni da parte di diversi go-routine si può verificare su questa variabile, allora hai ragione: non c'è bisogno di alcun synchonization.

Come si è detto che la variabile è stata inizializzata prima del avviata la routine, si è effettivamente al sicuro.

+0

E il fatto che le variabili modificate in un thread del sistema operativo potrebbero non essere visibili da un altro thread del sistema operativo, a meno che l'accesso non sia incluso nella sincronizzazione esplicita come sync.Mutex. So che stiamo parlando di goroutine ma sotto il cofano si passa ai thread OS, anche se non sempre. Come si relaziona con l'inizializzazione della variabile prima dell'inizio di goroutine, golang esegue la sincronizzazione implicita delle variabili catturate da qualche parte all'interno prima che inizi la goroutine? – let4be

+1

Abbiamo bisogno di essere precisi sul termine "visibile" qui: Naturalmente una variabile è visibile (come in: visibile a tutti) per ogni thread di un dato processo. Il problema è: una ** modifica ** fatta dal thread A visibile al thread B ** in tempo **. Questo potrebbe non essere il caso, se i due thread stanno accedendo alla variabile ** contemporaneamente **. Ma come il primo thread (lo uso in questo modo per le go-routines: i due si comportano in modo molto simile) ha da tempo finito le sue modifiche prima ancora che esistesse il secondo, siamo al sicuro. Non esiste alcuna sincronizzazione implicita dal runtime go, la sincronizzazione implicita viene eseguita dal codice. –

1

Sì, è sicuro. Secondo Go Memory Model:

  • la dichiarazione go che inizia una nuova goroutine avviene prima che inizi l'esecuzione del goroutine
  • all'interno di una singola goroutine, il che accade-prima di ordine è l'ordine espressa dal programma

Ciò significa che tutte le modifiche alle variabili che hai fatto prima di iniziare una goroutine sono visibili all'interno di questa goroutine.

Risposta alla domanda aggiuntiva: dipende. Generalmente se r.goroutine() è stato modificato r.something e si desidera leggerlo da un'altra goroutine è necessario utilizzare la sincronizzazione.