2016-10-16 2 views
10

Ich kann die Implementierung von AtomicCmpExchange nicht finden (scheint versteckt zu sein), also weiß ich nicht, was es tut.Ist AtomicCmpExchange auf allen Plattformen zuverlässig?

Ist AtomicCmpExchange zuverlässig auf allen Plattformen? Wie wird es intern umgesetzt? Benutzt es so etwas wie einen kritischen Abschnitt?

Ich habe dieses Szenario:

Mainthread:

Target := 1; 

Thread1:

x := AtomicCmpExchange(Target, 0, 0); 

Thread2:

Target := 2; 

Thread3:

Target := 3; 

Wird x immer eine ganze Zahl 1, 2 oder 3 sein, oder könnte es etwas anderes sein? Ich meine, selbst wenn die AtomicCmpExchange(Target, 0, 0) fehlgeschlagen, den Wert zu tauschen, gibt es eine "gültige" Ganzzahl (ich meine, nicht eine halbe gelesene Integer, zum Beispiel wenn ein anderer Thread bereits begonnen hat, den Wert halb zu schreiben)?

Ich möchte vermeiden, einen kritischen Abschnitt zu verwenden, ich brauche maximale Geschwindigkeit.

Antwort

16

AtomicCmpExchange ist, was als intrinsic routine, or a standard function bekannt ist. Es ist dem Compiler intrinsisch bekannt und kann eine sichtbare Implementierung haben oder nicht. Zum Beispiel ist Writeln eine Standardfunktion, aber Sie werden keine einzige Implementierung dafür finden. Der Compiler unterteilt es in mehrere Aufrufe von Funktionen auf niedrigerer Ebene in System.pas. Einige Standardfunktionen wie Inc() und Dec() haben keine Implementierung in System.pas. Der Compiler erzeugt Maschinenanweisungen, die zu einfachen INC oder DEC Anweisungen gehören.

Wie Inc() oder Dec(), AtomicCmpExchange() wird mit dem Code implementiert, der für eine bestimmte Plattform benötigt wird. Es erzeugt Inline-Anweisungen. Für x86/x64 wird eine CMPXCHG-Anweisung erzeugt (zusammen mit allen Einstellungen, die notwendig sind, um Variablen/Werte in die Register zu bekommen). Für ARM wird es einige weitere Anweisungen rund um die LDREX und STREX Anweisungen generieren.

So ist die direkte Antwort auf Ihre Frage ist, dass auch in Assembler-Code aufrufen, müssen Sie nicht viel effizienter bekommen als mit der Standardfunktion zusammen mit anderen wie AtomicIncrement, AtomicDecrement und AtomicExchange.

+1

Ja, es wird immer eine gültige Ganzzahl zurückgegeben. Wenn der Wert des Ziels mit dem Comparand übereinstimmt, wird der Wert getauscht und der Rückgabewert ist der vorherige Wert des Ziels. Wenn das Ziel nicht übereinstimmt, wird der Wert zurückgegeben. All dies geschieht atomar, was bedeutet, dass es ohne die Sorge, dass Zwischenzustände es vermasseln, abgeschlossen wird. –

+3

Es ist auch erwähnenswert, dass die Variablen ausgerichtet werden müssen –

+0

Microsoft sagt, dass die Ausrichtung erforderlich ist (für x86 und x64), aber Intel scheint nicht zu stimmen: http://StackOverflow.com/Questions/1415256/AusrichtungsAnforderungen-für-atomare -x86-Anweisungen – Alexandre

Verwandte Themen