Gleichzeitiges Schreiben auf stdout: Thread-Sicherheitsanalyse
In einer kürzlichen Diskussion wurde ein Teil des Go-Codes vorgestellt, der eine Debatte über Threads auslöste Sicherheit beim gleichzeitigen Schreiben nach stdout. Der betreffende Code ist:
<code class="go">package main import ( "fmt" "os" "strings" ) func main() { x := strings.Repeat(" ", 1024) go func() { for { fmt.Fprintf(os.Stdout, x+"aa\n") } }() go func() { for { fmt.Fprintf(os.Stdout, x+"bb\n") } }() go func() { for { fmt.Fprintf(os.Stdout, x+"cc\n") } }() go func() { for { fmt.Fprintf(os.Stdout, x+"dd\n") } }() <-make(chan bool) }</code>
Thread-Sicherheitsüberlegungen:
Es stellt sich die Frage, ob dieser Code threadsicher ist, wenn mehrere Goroutinen gleichzeitig auf stdout schreiben. Es wurden verschiedene Quellen und Meinungen zu diesem Thema genannt, eine definitive Antwort konnte jedoch nicht gefunden werden. Lassen Sie uns näher auf das Thema eingehen.
Verhalten des fmt-Pakets:
Die Funktionen des fmt-Pakets nehmen einfach eine io.Writer-Implementierung und rufen darauf Write() auf. Die Funktionen selbst sind threadsicher, was bedeutet, dass mehrere gleichzeitige Aufrufe von fmt.F*-Funktionen sicher sind. Die Implementierung des gleichzeitigen Schreibens auf stdout hängt jedoch vom spezifischen verwendeten „Writer“ ab.
„Writer“-Implementierungen:
Zwei Hauptkategorien von „Writern“ sind relevant :
POSIX-Semantik:
Im Fall von Dateideskriptoren erfordert POSIX das Schreiben (2) Aufrufe müssen atomar sein, wenn sie mit regulären Dateien oder symbolischen Links arbeiten. Dies bedeutet, dass in unserem Fall, in dem davon ausgegangen wird, dass stdout ein Dateideskriptor ist, Schreibaufrufe atomar sein sollten.
Implementierung der Go-Standardbibliothek:
Die Go-Standardbibliotheken Wrapper um Dateideskriptoren und Sockets sind so konzipiert, dass sie Schreibvorgänge 1:1 dem zugrunde liegenden Objekt zuordnen. Dadurch wird die Möglichkeit ausgeschlossen, dass Schreibaufrufe aufgeteilt oder zusammengeklebt werden.
Schlussfolgerung:
Basierend auf den verfügbaren Informationen und der zugrunde liegenden Semantik des POSIX-Write(2)-Aufrufs , der bereitgestellte Code unterliegt keinem Datenwettlauf. Allerdings kann die in den zugrunde liegenden Dateideskriptor geschriebene Ausgabe in einer unvorhersehbaren Reihenfolge vermischt sein. Dieses Verhalten wird durch Faktoren wie die Kernelversion des Betriebssystems, die Go-Version, die Hardware und die Systemlast beeinflusst.
Um sicherzustellen, dass die Ausgabe jedes spezifischen fmt.Fprint*-Aufrufs als zusammenhängender Teil in der resultierenden Ausgabe erscheint , wird empfohlen, die Aufrufe mithilfe einer Sperre oder mithilfe des Protokollpakets zu serialisieren, das über eigene Sperrmechanismen verfügt.
Das obige ist der detaillierte Inhalt vonIst das gleichzeitige Schreiben auf „stdout' in Go Thread-sicher? Eine detaillierte Analyse des Verhaltens von „fmt.Fprintf'.. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!