Heim  >  Artikel  >  Backend-Entwicklung  >  Warum führt das Erhöhen einer Variablen durch meine Goroutine zu unerwarteten Ergebnissen?

Warum führt das Erhöhen einer Variablen durch meine Goroutine zu unerwarteten Ergebnissen?

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2024-10-29 20:38:29625Durchsuche

Why Does My Goroutine Incrementing a Variable Produce Unexpected Results?

Ist dies ein Ergebnis der Compiler-Optimierung?

In diesem Codeausschnitt wird eine Goroutine gestartet und erhöht wiederholt die Variable i:

<code class="go">package main

import "time"

func main() {
    i := 1
    go func() {
        for {
            i++
        }
    }()
    <-time.After(1 * time.Second)
    println(i)
}</code>

Die Ausgabe ist jedoch immer 1. Dieses Verhalten kann dem Go-Speichermodell und der spezifischen Implementierung dieses Codes zugeschrieben werden.

Das Go-Speichermodell

Das Go-Speichermodell definiert die Bedingungen Dadurch kann garantiert werden, dass beim Lesen einer Variablen in einer Goroutine Werte beobachtet werden, die durch Schreibvorgänge in dieselbe Variable in einer anderen Goroutine erzeugt werden. Es betont die Bedeutung der Synchronisierung für den gleichzeitigen Zugriff auf gemeinsam genutzte Daten.

Synchronisierung weglassen

Im angegebenen Code:

  • Die Zuweisung zu i (d. h. i ) Es folgt kein Synchronisierungsereignis, was darauf hinweist, dass Änderungen für andere Goroutinen möglicherweise nicht sofort sichtbar sind.
  • Der Compiler kann diese Schleifenoptimierung optimieren, indem er sie zu einem No-Op vereinfacht.

Optimierung durch den Compiler

Ein aggressiver Compiler könnte die i-Anweisung löschen und die Goroutine effektiv reduzieren auf:

<code class="go">for {}</code>

Beispiel mit Synchronisierung

Um zu zeigen, dass das Problem auf die Ursache zurückzuführen ist Betrachten Sie aufgrund der fehlenden Synchronisierung den folgenden Code:

<code class="go">package main

import (
    "sync"
    "time"
)

func main() {
    mx := new(sync.Mutex)
    i := 1
    go func() {
        for {
            mx.Lock()
            i++
            mx.Unlock()
        }
    }()
    <-time.After(1 * time.Second)
    mx.Lock()
    println(i)
    mx.Unlock()
}</code>

In diesem Fall ist die Ausgabe nicht mehr 1, sondern wie erwartet eine große Zahl. Der sync.Mutex sorgt für Synchronisierung und stellt sicher, dass beide Goroutinen auf kontrollierte Weise auf i zugreifen, wodurch die Goroutine i inkrementieren kann und die Änderungen für die Hauptroutine sichtbar werden.

Das obige ist der detaillierte Inhalt vonWarum führt das Erhöhen einer Variablen durch meine Goroutine zu unerwarteten Ergebnissen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn