2013-08-28 9 views
12

Ich bin neu in der Sprache, also ertragen Sie mit mir.Unterstützt Go volatile/nichtflüchtige Variablen?

Ich bin gespannt, wie GO behandelt Datenspeicher für Threads in dem Sinne, dass nicht-lokale Variablen können auch nicht-flüchtig sein, wie in Java zum Beispiel.

GO hat das Konzept von Kanal, der durch seine Art - Inter-Thread-Kommunikation bedeutet, dass es Prozessor-Cache umgeht und direkt in Heap liest/schreibt.

Haben auch keinen Verweis auf flüchtige in der go lang Dokumentation gefunden.

+0

Hier wird angenommen, dass 'volatile' die Bedeutung von Java/.NET anstelle von C/C++ hat. –

Antwort

3

In der Dokumentation Go Memory Model wird erläutert, warum das Konzept von "volatile" in Go keine Anwendung findet.

Locker: Unter anderem sind die Goroutinen frei, um goroutine-lokale Änderungen in Registern zu speichern, so dass diese Änderungen von anderen Goroutines nicht beobachtet werden können. Um diese Änderungen in den Speicher zu "leeren", muss eine Synchronisation durchgeführt werden. Entweder durch Sperren oder durch Kommunikation (Kanal senden oder empfangen).

+2

Das Go-Speichermodell sagt nichts darüber aus, warum Volatile nicht unterstützt wird. Es erklärt auch nicht, warum Volatile in Go keine Anwendung findet. Stattdessen erklärt es, wie es funktioniert. Die Existenz von volatile ist genau dazu gedacht, Variablen zu markieren, die ansonsten auch anderen Regeln in C oder C++ folgen würden. –

+0

Was ist mit Variablen, die außerhalb einer Funktion sitzen, können sie von der Funktion aus aufgerufen werden? Wenn dies der Fall ist, wenn diese Funktion in einem separaten Thread ausgeführt wird, wird diese äußere Variable beim Aktualisieren mit Heap synchronisiert oder nicht? – Raul

+1

@GustavoNiemeyer: Wenn Sie das aus diesem Dokument nicht ableiten können, bedeutet das nicht, dass es nicht da ist. Und ich habe tatsächlich den Hinweis auf die Ableitung im Absatz "Lose" eingefügt. Volatile _memory_-Variablen können durch erzwungenen Zugriff synchronisiert werden (das ist, was C tut). Werte, die nur in einem Register einer anderen Goroutine vorhanden sind, können nicht auf die gleiche Weise behandelt werden. Und das Speichermodell erlaubt eine solche Implementierung, während C niemals eine flüchtige Variable im Register speichert, wenn sie aktualisiert wird. – zzzz

5

Die einfache Antwort ist, dass volatile von der aktuellen Go-Spezifikation, Zeitraum nicht unterstützt wird.

Wenn Sie einen der Anwendungsfälle haben, in denen flüchtige Elemente erforderlich sind, z. B. niedriger atomarer Speicherzugriff, der von existingpackages in der Standardbibliothek nicht unterstützt wird, oder ungepufferter Zugriff auf Hardware zugeordneten Speicher, müssen Sie Verknüpfung in einer C- oder Assembly-Datei.

Beachten Sie, dass Sie, wenn Sie C oder Assembly verwenden, wie von der GC-Compiler-Suite verstanden, nicht einmal cgo dafür benötigen, da die [568] c C/asm-Compiler auch damit umgehen können.

Sie können Beispiele davon in Gos Quellcode finden. Zum Beispiel:

Grep für viele andere Fälle.

Wie der Speicherzugriff in Go funktioniert, finden Sie unter The Go Memory Model.

10

TL; DR: Go hat kein Schlüsselwort, um eine Variable sicher zu machen, damit mehrere Goroutinen sie schreiben/lesen können. Verwenden Sie das Paket sync/atomic dafür. Oder besser noch Do not communicate by sharing memory; instead, share memory by communicating.


Zwei Antworten für die two meanings of volatile volatile Ven diagram

.NET/Java Gleichzeitigkeit

Einige Auszüge aus dem Go Memory Model.

Wenn die Auswirkungen eines goroutine muss von einem anderen goroutine beobachtet werden, einen Synchronisationsmechanismus, wie beispielsweise eine Sperre verwenden oder Kommunikationskanal eine relative Ordnung herzustellen.

Eines der Beispiele aus dem Abschnitt Incorrect Synchronization ist ein Beispiel für einen aktiven Wartezustand.

Schlimmer noch, es gibt keine Garantie, dass der Schreib getan wird je nach Haupt beobachtet werden, da es keine Synchronisationsereignisse zwischen den beiden Fäden sind. Die Schleife in main wird nicht garantiert beendet.

Tatsächlich wird dieser Code (play.golang.org/p/K8ndH7DUzq) nie beendet.

C/C++ Nicht-Standard-Speicher

Gos Speichermodell bietet keine Möglichkeit, Nicht-Standard-Speicher zu adressieren. Wenn Sie unformatierten Zugriff auf den E/A-Bus eines Geräts haben, müssen Sie Assembly oder C verwenden, um Werte sicher in die Speicherpositionen zu schreiben. Ich musste das immer nur in einem Gerätetreiber tun, was Go generell ausschließt.

+2

Der referenzierte Code wird nicht beendet, da die Hauptschleife die Ausführung der go-Routine blockiert. Durch Erhöhung der Laufzeit.GOMAXPROCS auf 2 wird der Code beendet: https://play.golang.org/p/n-sC8jISyw – PSanetra

Verwandte Themen