2017-07-23 2 views
2

Ich lese Go-in-Aktion. Dieses Beispiel stammt aus Kapitel 6/Listing09.go.Warum Race Condition mit Goroutine wird nicht irgendwann passieren?

Wenn Sie diesen Code in play.golang.org ausführen, wird es 2, genau wie das Buch. Aber mein Mac drucken 4 die meiste Zeit, einige Zeit 2, einige Zeit sogar 3.

$ go run listing09.go 
Final Counter: 2 
$ go run listing09.go 
Final Counter: 4 
$ go run listing09.go 
Final Counter: 4 
$ go run listing09.go 
Final Counter: 4 
$ go run listing09.go 
Final Counter: 4 
$ go run listing09.go 
Final Counter: 2 
$ go run listing09.go 
Final Counter: 4 
$ go run listing09.go 
Final Counter: 2 
$ go run listing09.go 
Final Counter: 3 

sysinfo go Version go1.8.1 darwin/amd64 macOS sierra Pro Macbook

Erklärung von der Buch (p140)

Jede goroutine überschreibt die Arbeit der anderen. Dies geschieht, wenn der Goroutinustausch stattfindet. Jede Goroutine erstellt ihre eigene Kopie der Zählervariable und wird dann für die andere Goroutine ausgelagert. Wenn der goroutine wieder Zeit für die Ausführung gegeben wird, hat sich der Wert der Zählervariablen geändert, aber die goroutine aktualisiert ihre Kopie nicht. Stattdessen inkrementiert es die Kopie, die es hat, und setzt den Wert zurück auf die Zählervariable und ersetzt die Arbeit, die die andere Goroutine ausgeführt hat.

Nach dieser Erklärung sollte dieser Code immer 2.

  1. drucken Warum ich 4 und 3 erhalten? Ist es, weil Race Condition nicht passiert ist?

  2. Warum Spielplatz immer 2 bekommen?


Update:

Nachdem ich runtime.GOMAXPROCS(1) gesetzt, beginnt es 2 zu drucken, kein 4, einige 3. ich die play.golang.org erraten ist so konfiguriert, einen logischen Prozessor zu haben.

Das richtige Ergebnis 4 ohne Race Condition. Ein logischer Prozessor bedeutet einen Thread. GO hat die gleichen logischen Prozessoren wie die physischen Kerne standardmäßig. Also, warum führt ein Thread (ein logischer Prozessor) zu Race Condition, während mehrere Threads die richtige Antwort drucken?

Können wir sagen, die Erklärung aus dem Buch ist falsch, da wir auch 3 und 4 bekommen? Wie es 3 bekommen? 4 ist richtig.

+1

Milos Antwort ist großartig, aber Go kann Ihnen auch in Fällen, in denen es Sie nicht beißt (das "Rennen" passiert immer; manchmal gewinnen Sie, manchmal verlieren Sie verschiedene Wege) von dieser Rassenbedingung erzählen. Versuchen Sie es mit 'go run --race test.go' und Sie sehen die genaue Codezeile, die vom Rennen betroffen ist. –

+0

@RobNapier vielen Dank –

Antwort

2

Race-Bedingungen sind per Definition nichtdeterministisch. Dies bedeutet, dass, während Sie die meiste Zeit eine bestimmte Antwort bekommen, es nicht immer so sein wird.

Indem Sie racycode auf mehreren Kernen laufen lassen, erhöhen Sie die Anzahl der Möglichkeiten erheblich, daher erhalten Sie eine breitere Auswahl an Ergebnissen.

Weitere Informationen zu den Rennbedingungen finden Sie unter this post oder this Wikipedia article.

+0

Single-Thread kann nur auf einem Kern laufen, oder? Bei mehreren Threads wird häufiger 4 (das korrekte Ergebnis) gedruckt. Warum ist das ? Ich habe ein Update zu meiner Frage. Vielen Dank ! –

+0

Dies ist eine der "Freuden" der Rennbedingungen. Es gibt keine wirkliche Möglichkeit zu sagen, was passiert oder warum. Warum produziert es öfter "richtige" Ergebnisse auf mehr Kernen? Es hat wahrscheinlich etwas mit den genauen relativen Geschwindigkeiten verschiedener Funktionen zu tun, und wenig Details der Scheduler-Implementierung. Wenn Sie den Code oder die Anzahl und Geschwindigkeit der Kerne ändern, werden sich die Ergebnisse wahrscheinlich zufällig ändern. –

+0

Hallo, wenn ich runtime.Gosched() kommentiere, wird es immer 4 sein, keine Race Condition, oder? –