Grundlegendes zu std :: atomic :: compare_exchange_weak () in C ++ 11
bool compare_exchange_weak (T& expected, T val, ..);
compare_exchange_weak()
ist eines der in C ++ 11 bereitgestellten Vergleichsaustauschprimitive. Es istschwach in dem Sinne, dass es false zurückgibt, auch wenn der Wert des Objekts gleich istexpected
. Das ist wegenfalsches Versagen Auf einigen Plattformen, auf denen eine Folge von Anweisungen (anstelle von x86) zur Implementierung verwendet wird. Auf solchen Plattformen kann ein Kontextwechsel, ein erneutes Laden derselben Adresse (oder Cache-Zeile) durch einen anderen Thread usw. das Grundelement zum Scheitern bringen. Es istspurious
da es nicht der Wert des Objekts ist (ungleichexpected
), bei dem die Operation fehlschlägt. Stattdessen ist es eine Art Zeitprobleme.
Was mich jedoch verwundert, ist, was in C ++ 11 Standard (ISO / IEC 14882) gesagt wird.
29.6.5. Eine Konsequenz des Fehlschlags ist, dass sich fast alle Verwendungen von schwachem Vergleichen und Austauschen in einer Schleife befinden.
Warum muss es in einer Schleife seinfast alle Verwendungen ? Bedeutet das, dass wir eine Schleife ausführen sollen, wenn sie aufgrund von falschen Fehlern fehlschlägt? Wenn dies der Fall ist, warum stören wir uns dann daran?compare_exchange_weak()
und die Schleife selbst schreiben? Wir können nur verwendencompare_exchange_strong()
was ich denke, sollte für uns falsche Fehler loswerden. Was sind die häufigsten Anwendungsfälle voncompare_exchange_weak()
?
Eine andere Frage im Zusammenhang. In seinem Buch "C ++ Concurrency In Action" sagt Anthony:
//Because compare_exchange_weak() can fail spuriously, it must typically
//be used in a loop:
bool expected=false;
extern atomic<bool> b; // set somewhere else
while(!b.compare_exchange_weak(expected,true) && !expected);
//In this case, you keep looping as long as expected is still false,
//indicating that the compare_exchange_weak() call failed spuriously.
Warum ist!expected
gibt es im schleifen zustand? Ist es dort, um zu verhindern, dass alle Fäden verhungern und für einige Zeit keine Fortschritte machen?
Bearbeiten: (eine letzte Frage)
Auf Plattformen, auf denen keine einzige Hardware-CAS-Anweisung vorhanden ist, werden sowohl die schwache als auch die starke Version unter Verwendung von LL / SC (wie ARM, PowerPC usw.) implementiert. Gibt es also einen Unterschied zwischen den folgenden beiden Schleifen? Warum, wenn überhaupt? (Für mich sollten sie eine ähnliche Leistung haben.)
// use LL/SC (or CAS on x86) and ignore/loop on spurious failures
while (!compare_exchange_weak(..))
{ .. }
// use LL/SC (or CAS on x86) and ignore/loop on spurious failures
while (!compare_exchange_strong(..))
{ .. }
Ich komme zu dieser letzten Frage, die ihr alle erwähnt, dass es innerhalb einer Schleife möglicherweise einen Leistungsunterschied gibt. Dies wird auch im C ++ 11-Standard (ISO / IEC 14882) erwähnt:
Wenn sich ein Vergleich und Austausch in einer Schleife befindet, bietet die schwache Version auf einigen Plattformen eine bessere Leistung.
Wie oben analysiert, sollten zwei Versionen in einer Schleife die gleiche / ähnliche Leistung erbringen. Was ist das, was ich vermisse?