2017-10-07 3 views
0

Entschuldigt, wenn dies wurde bereits beantwortet, oder wenn ich etwas fehlt offensichtlich.Sind verschachtelte atomare Operationen garantiert atomar?

Ich versuche, wie tief die Garantien der Unteilbarkeit für std::atomic gehen zu verstehen. wenn wir zum Beispiel

std::atomic<int> a(0); 
a.store(1); 

die Speicheroperation Atom wird. Doch was passiert, wenn wir atomare Operationen verschachtelt sind, wie folgt aus:

std::atomic<int> a(0); 
std::atomic<int> b(1); 
a.store(++b); 

Mein Verständnis ist, dass ++b atomar ist, und so ist store(). Habe ich Recht davon ausgehen, dass dies gewährleistet ist 2 atomar speichern in a?

Noch wichtiger ist, wenn a und b zwischen Threads gemeinsam benutzt werden T1 und T2, ist garantiert, dass a.store(++b); von beiden Threads durchgeführt wird der inkrementierte Wert von b speichern (wie durch die jeweiligen Fäden aus gesehen) in a atomar in jedem Faden? Mit anderen Worten kann, Gewinde T2 „butt in“ und erhöhen b nochmals nachT1 bereits einmal erhöht hat aber vor wird das Ergebnis in a von T1 gespeichert?

+0

Unter der Annahme, 'b' zwischen Gewinde freigegeben ist, Inkrementieren von 'b' passieren kann, bevor 'a.store (++ b);'. daher ist der Wert von "a" keine Garantie für "2". – Jarod42

Antwort

2

Der Zuwachs ist atomar, und der Laden ist atomar, aber die beiden Operationen sind nicht zusammen. Es ist möglich, dass der erste Thread b inkrementiert, suspendiert wird, dann ein weiterer Thread inkrementiert b und speichert diesen Wert in a, dann wird der erste Thread fortgesetzt und speichert seinen (jetzt veralteten) Wert von b in a.

+0

'b' wird nur einmal ausgewertet. also würde aus OP-Beispiel a "2" speichern, selbst wenn "b" jetzt "3" ist. – Jarod42

+0

Vielen Dank, ich so viel vermutet, aber es ist gut, es bestätigt zu haben. Also gibt es keine "verschachtelte" Atomarität. – cantordust

1

Atomicity komponieren nicht.

sonst niemand jemals Unter der Annahme, schreibt a und b und ein anderer Thread zu lesen versucht, beide, nachdem sie existieren, und sie lesen b dann a, möglich liest genau:

{b,a} 
{1,0} 
{2,0} 
{2,2} 

wenn sie a dann lesen b:

{a,b} 
{0,1} 
{0,2} 
{2,2} 

in diesem Fall die die gleiche wie b dann a ist.

+0

Die einzige Garantie ist, dass der Lese-Thread nicht '{0, ' {1,2} ' bekommen kann Mit anderen Worten,' b' wird nicht in 'a' gespeichert, bevor es mindestens inkrementiert wird Einmal. Ist das korrekt? – cantordust

1
a.store(++b); 

entspricht

int temp = ++b; 
/* other threads can modify `b` but its value has been save in temp ... */ 
a.store(temp); 
+0

Nun, es gibt ein Argument, dass der Pre-Inkrement-Operator keinen temporären Wert erstellt. – cantordust

+0

Ich meine, dass 'operator ++' gibt ein 'int' nicht ein' std :: atomic ', so zukünftige Änderung von' b' wirkt sich nicht auf Wert in 'a' gespeichert. – Jarod42