2015-08-12 12 views
5

I definiert eine Variable (r.something) innerhalb eines ObjektsIst Synchronisation erforderlich?

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

    go r.goroutine() 
} 

während r.goroutine Wert in r.something ohne Synchronisation verwendet gespeichert. Niemand sonst wird diesen Wert lesen/schreiben außer r.goroutine()

Ist es sicher, ohne Synchronisierung zu gehen?

Mit anderen Worten: Ich möchte einige Variable von einem goroutine woanders vor starten goroutine initialisiert wiederzuverwenden. Ist das sicher?

Zusätzliche Frage: Nachdem r.goroutine() beendet Ich möchte r.etwas von woanders verwenden (ohne Lese/Schreib-Überlappung mit anderen goroutines). Ist es auch sicher?

Antwort

5

Natürlich ist das sicher, sonst könnte das Programmieren in Go ein Albtraum sein (oder zumindest viel weniger angenehm). The Go Memory Model ist ein interessantes Stück zu lesen.

Die Routineerstellung ist ein Synchronisationspunkt. Es ist ein Beispiel sehr ähnlich wie bei Ihnen:

var a string 

func f() { 
    print(a) 
} 

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

mit dem folgenden Kommentar:

Aufruf hallo druckt „Hallo, Welt“ irgendwann in der Zukunft (vielleicht nach hallo zurückgekehrt ist).

Dies liegt daran:

Die Aussage gehen, die eine neue goroutine beginnt vor der Ausführung beginnt die goroutine passiert.

Das Wort vor entscheidend ist hier, wie es Routine Schöpfung bedeutet (in einem Thread) muss (möglicherweise in anderen Thread) mit seinem Start synchronisiert werden, so schreibt ein muss durch die neue Routine sichtbar sein .

+0

Völlig macht Sinn! Danke @tomasz – let4be

3

Wenn es keine Situation, wo eine Überlappung von lesen und Operationen durch verschiedene Go-Routinen schreibt auf diesen Variablen auftreten kann, dann sind Sie hier richtig: Es gibt keine Notwendigkeit für eine synchonization ist.

Wie Sie erwähnt haben, dass die Variable initialisiert wurde vor Ihre Go-Routine begann, sind Sie in der Tat sicher.

+0

Was ist mit der Tatsache, dass Variablen, die in einem OS-Thread geändert wurden, möglicherweise nicht von einem anderen OS-Thread sichtbar sind, es sei denn, der Zugriff wird in eine explizite Synchronisation wie sync.Mutex eingeschlossen. Ich weiß, wir reden über Goroutines, aber unter der Haube geht es auf OS-Threads, wenn auch nicht immer. Wie verhält es sich mit der Variableninitialisierung vor dem Starten des Goroutines, führt Golang eine implizite Synchronisation der erfassten Variablen irgendwo vor dem Start der Goroutine durch? – let4be

+1

Über den Begriff "sichtbar" müssen wir hier genau sein: Natürlich ist für jeden Thread eines bestimmten Prozesses eine Variable sichtbar (wie in: überhaupt sichtbar). Das Problem ist: Ist eine ** Änderung ** von Thread A sichtbar für Thread B ** pünktlich **. Dies ist möglicherweise nicht der Fall, wenn die beiden Threads ** gleichzeitig auf die Variable ** zugreifen. Aber als der erste Thread (ich benutze das synonym für Go-Routinen: die beiden verhalten sich sehr ähnlich) hat er seine Modifikationen lange vor dem zweiten abgeschlossen, wir sind in Sicherheit. Es gibt keine implizite Synchronisation durch die Go-Laufzeit, die implizite Synchronisation erfolgt durch Ihren Code. –

1

Ja, es ist sicher. Nach Go Memory Model:

  • die Go-Anweisung, die eine neue goroutine beginnt vor der Ausführung
  • innerhalb eines einzigen goroutine beginnt die goroutine geschieht, das geschieht zuvor, um die Bestellung durch das Programm

ausgedrückt ist Dies bedeutet, dass alle Änderungen an Variablen, die Sie vor dem Starten einer Goroutine vorgenommen haben, in dieser Goroutine sichtbar sind.

Antwort auf Ihre zusätzliche Frage: es kommt darauf an. Wenn Sie geändert r.something ändern und wenn Sie es von einer anderen Goroutine lesen möchten, müssen Sie die Synchronisierung verwenden.