2012-10-13 10 views
7

Betrachten Sie die folgenden zwei Alternativen von der höheren Zahl zwischen currentPrice bekommen und 100 ...Ist der ternäre Operator (? :) Thread in C# sicher?

int price = currentPrice > 100 ? currentPrice : 100 

int price = Math.Max(currentPrice, 100) 

ich diese Frage gestellt, weil ich über einen Kontext dachte, wo die currentPrice Variablen von anderen Threads bearbeitet werden könnten.

Im ersten Fall ... konnte price einen niedrigeren Wert als 100 erhalten?

Ich denke an die folgende:

if (currentPrice > 100) { 
    //currentPrice is edited here. 
    price = currentPrice; 
} 

Antwort

8

Es ist nicht thread.

?: ist die Verknüpfung nur für normale if, so dass Ihre if Probe ? ein Äquivalent ist - Sie Preis von weniger als 100 erhalten kann, wenn es keine Verriegelung außerhalb dieses Codes ist.

+0

Entgegengesetzte Antwort in wenigen Minuten? : D – dotNETbeginner

+0

@dotNETbeginner :) Gute Beobachtung. als ich meine erste antwort gelesen habe, wollte ich mir auch -10 geben. –

3

Theoretisch wird currentPrice zweimal gelesen. Einmal zum Vergleich, einmal zur Zuordnung.

In der Praxis kann der Compiler den Zugriff auf die Variable zwischenspeichern. Ich weiß nicht, über C#, aber in C++ auf x86:

MOV AX, [currentPrice] 
MOV BX, 100 ;cache the immediate 
CMP AX, BX 
JLE $1  ;if(currentPrice > 100){ 
MOV AX, BX 
$1:   ;} 
MOV [BP+price], AX ;price is on the stack. 

Das gleiche Last-once-Optimierung geschieht in Java-Bytecode, es sei denn Current volatile deklariert wird.

Also, in der Theorie kann es passieren. In der Praxis wird es auf den meisten Plattformen nicht funktionieren, aber darauf können Sie nicht zählen.

3

Kein Spezialist in C#, aber sogar var ++ ist nicht Thread speichern, da kann aus dem Lesen/Schreiben von Register in der Montage übersetzt werden.

Ternärer Operator ist viel komplizierter. Es hat 3 Teile, während jedes Teil endlos groß sein kann (z. B. Anruf zu einer Funktion). Daher ist es ziemlich einfach zu folgern, dass ternärer Operator nicht threadsicher ist.

+1

+1; Ich fürchte, x86 lässt Sie nicht 'INC'rement einen Speicherort, so dass es _wille_ als eine Verschiebung in die Registrierung/Inkrement/verschieben in den Speicher-Combo übersetzt werden. –

1

Wie von anderen angegeben, könnte es zwischengespeichert werden, aber die Sprache erfordert es nicht.

Sie können Interlocked.CompareExchange verwenden, wenn Sie sperrlose Thread-Zuweisungen benötigen. Aber als Beispiel würde ich eine grobkörnigere Sperrstrategie wählen.