Nach dem, was ich von Herb Sutter und anderen gelesen habe, würde man denken, dass die volatile
gleichzeitige Programmierung völlig orthogonale Konzepte waren, zumindest was C / C ++ betrifft.
In der GCC- Implementierung haben jedoch alle std::atomic
Mitgliedsfunktionen das volatile
Qualifikationsmerkmal. Gleiches gilt für Anthony Williams ' Implementierung von std::atomic
.
Also, was ist los , müssen meine atomic<>
Variablen sein volatile
oder nicht?
volatile
Sie daran, dass Garantien, die in einem einzelnen Thread lesen und schreiben, in der richtigen Reihenfolge ausgeführt werden und dass auf einem flüchtigen Objekt keine nichtflüchtigen Elementfunktionen aufgerufen werden können (genau wie bei const). Aber darüber hinaus habe ich keine Ahnung von Threads in C ++. Jedes Mal, wenn ich versuche, im Standard darüber zu lesen, fange ich an aufzugeben, da ich nicht in der Lage bin, die schiere Menge an Indirektionen und Logiken im Text xDAntworten:
Warum wird das
volatile
Qualifikationsmerkmal durchgehend verwendetstd::atomic
?Damit flüchtige Objekte auch atomar sein können. Siehe hier :
Das entsprechende Zitat ist
Müssen meine
atomic<>
Variablen seinvolatile
oder nicht?Nein, atomare Objekte müssen nicht flüchtig sein.
quelle
volatile
Operationen werden nur schriftlich bestellt. anderevolatile
Zugriffe.atomic<T>
Freigabe-, Erwerbs- und seq_cst-Operationen werden in der Reihenfolge bestellt. Ebene nicht-atomare Variablen, also Ihre eigene atomics rollt mit nurvolatile
können es nicht geben Ihnen die gleiche acq / rel Semantik ohne Barrieren.volatile atomic<T>
kann / wird in Zukunft nützlich sein, wenn Compiler die Als-ob-Regel nutzen, um die Atomik zu optimieren , z. B. um zu verhindern, dass "redundante" Schreibvorgänge mit einem Fortschrittszähler zusammengeführt werden.volatile sig_atomic_t
, aber die meisten realen Implementierungen haben,int
dass dies für Ladungen / Speicher natürlich atomar ist (Definition des Verhaltens). (Ich habe kürzlich eine große Antwort dazu geschrieben: MCU-Programmierung - C ++ O2-Optimierung bricht während der Schleife ab ) Trotzdem, wenn Sie eine Bestellung wünschen. Nicht-atomare Variablen (z. B. Interrupt-Handler schreibt einen normalen Puffer und setzt dann ein atomares Flag) können Sie eine entspannte atomare Last undatomic_signal_fence(memory_order_acquire)
im Hauptcode verwenden, um eine Neuordnung zur Kompilierungszeit zu verhindern.volatile
bei echten Compilern passiert. Die Anzahl der Dinge, die Sie sicher für die Interaktion zwischen einem Signal- oder Interrupt-Handler tun können, ist jedoch sehr begrenzt, und es hilft nicht, wenn Typen zu breit sind, um von Natur aus atomar zu sein. Aber solange du dabei bleibst, funktioniert es. Wie ich im Link in meinem vorherigen Kommentar gezeigt habe, können Sie C ++ 11 Relaxed Atomics verwendensignal_fence
, um alles,volatile
was für diesen Anwendungsfall möglich ist, genauso effizient und mit der Option zum Freigeben / Erfassen von Bestellungen mithilfe von zu tunsignalf_fence
.Um zusammenzufassen, was andere richtig geschrieben haben:
C / C ++
volatile
ist für Hardwarezugriff und Interrupts vorgesehen. C ++ 11atomic<>
dient zur Kommunikation zwischen Threads (z. B. in sperrenfreiem Code). Diese beiden Konzepte / Verwendungen sind orthogonal, aber sie haben überlappende Anforderungen, und deshalb haben die Leute die beiden oft verwechselt.Der Grund
atomic<>
für flüchtig qualifizierte Funktionen ist der gleiche Grund für const-qualifizierte Funktionen, da es im Prinzip möglich ist, dass ein Objekt sowohlatomic<>
als auchconst
und / oder istvolatile
.Wie mein Artikel hervorhob, ist eine weitere Quelle der Verwirrung natürlich, dass C / C ++
volatile
nicht mit C # / Java identisch istvolatile
(letzteres entspricht im Wesentlichen C ++ 11atomic<>
).quelle
volatile
Flags zu erfragen , um Fehler bei der Kompilierung von Thread-unsicherem Code zu erzeugen (indemvolatile
Instanzen verwendet werden, um die Verwendung der Schnittstelle zu sperren undconst_cast
das Flüchtige zu entfernen wenn ein Mutex erworben wird). Könnte es sinnvoll sein, zu diesem Zweck ein Typqualifikationsmerkmal 'threadsafe' oder ähnliches in die Sprache aufzunehmen (ich denke nur laut nach) ?Als const ist flüchtig transitiv. Wenn Sie eine Methode als deklarieren
volatile
, können Sie keine nichtflüchtige Methode oder eines ihrer Mitgliedsattribute aufrufen. Mitstd::atomic
Methodenvolatile
erlauben Sie Aufrufe vonvolatile
Mitgliedsmethoden in Klassen, die diestd::atomic
Variablen enthalten .Ich habe keinen guten Tag ... so verwirrend ... vielleicht hilft ein kleines Beispiel:
struct element { void op1() volatile; void op2(); }; struct container { void foo() volatile { e.op1(); // correct //e.op2(); // compile time error } element e; };
quelle