2009-02-10 12 views
10

Als nur Referenztypen und ein paar Primitive (einschließlich Float, aber nicht doppelt, ich bin mir nicht sicher, der Grund warum, ich bin glücklich, warum zu hören) kann als volatil erklärt werden, wenn ich ein Doppelpack in einer Klasse deklariere es dann als flüchtig (wie unten), wird die Doppeleigenschaft "lesen schreiben" threadsicher sein wie jede andere flüchtige, oder sollte ich immer noch auf Sperren achten?C# flüchtige Doppel

public class MyThreadedClass 
{ 
    volatile VolatileDouble voldub; 
} 

public class VolatileDouble 
{ 
    public double Double { get; set; } 
} 

Antwort

16

Grund, warum Doppel nicht flüchtig erklärt werden: Es ist 64 Bits, die es mehr als die Wortgröße auf x86 macht, was sie daran hindert, in der CLI flüchtig erklärt zu werden, wenn ich mich richtig erinnere.

Mit Ihrer aktuellen Antwort wird nur die Referenz als flüchtig behandelt. Das bedeutet, dass das Speichermodell sicherstellen wird, dass immer die neueste Referenz verwendet wird, aber es kann immer noch einen veralteten Wert verwenden.

würde ich mit Sperren gehen, wenn ich du wäre, aber eine Alternative ist Interlocked.Read und Interlocked.Exchange wirkt auf longs zu verwenden, in Verbindung mit BitConverter.Int64BitsToDouble und BitConverter.DoubleToInt64Bits. Sie könnten dies innerhalb einer VolatileDouble Struktur einkapseln. (Ich würde es wahrscheinlich zu einer Struktur und nicht zu einer Klasse machen.)

+0

Art der Verdacht auf, dass nur die Referenz flüchtig war, daher die Frage. Danke für die Bestätigung – johnc

+0

wenn er sichergestellt hat, dass der VolatileDouble unveränderlich ist, sollte er keine Probleme haben, richtig? –

+0

Danke auch für die Interlocked und BitConverter Vorschläge, löste einen ganz neuen Gedankengang – johnc

5

Um wie oben beschrieben arbeiten zu können, müsste sie unveränderlich sein (kein Setter) - vielleicht mit einigen impliziten Konvertierungsoperatoren. Anderenfalls könnten Personen den Wert ändern, ohne die (flüchtige) Referenz zu ändern.

public class MyThreadedClass 
{ 
    volatile Box<double> volDouble = 123.45; 
} 

public class Box<T> where T : struct 
{ 
    private readonly T value; 
    public Box(T value) { this.value = value; } 
    public T Value {get {return value;}} 

    // explicit as nulls are a problem... 
    public static explicit operator T(Box<T> box) { 
     return box.value; } 
    public static implicit operator T?(Box<T> box) { 
     return box == null ? new T?() : new T?(box.value); } 
    public static implicit operator Box<T>(T value) { 
     return new Box<T>(value); } 
    public static implicit operator Box<T>(T? value) { 
     return value.HasValue ? new Box<T>(value.Value) : null; } 
} 

Darüber hinaus - Verriegelung wäre die beste Option.

+0

Meinst du keinen Setter? –

+0

Ich tue ;-p (oops!) –

+0

netter Code, aber ich denke, ich gehe zurück zum Sperren – johnc

3

Sie erklären gerade, dass die Referenz flüchtig ist nicht die Instanz, so dass das Problem nicht gelöst wird.

+0

Vermutet also, daher die Frage, danke für die Bestätigung – johnc

0

Die flüchtige Dokumentation ist etwas, wie irreführend ...

, wenn die MSDN-Dokumentation sagt, dass sie die aktuellsten Wert verwendet, was bedeutet es ??? Ich bin sicher, dass dies in einem einfachen Wert nicht zu Verwirrung führt, aber was ist mit einer Referenz, da Brian Rasmussen Sie gerade über die Ref nicht die tatsächliche Instanz (und damit die interessanten Daten) sprechen.

Aus meiner Sicht mit flüchtig ist keine gute Idee, und ich würde für das Schloss gehen, jedenfalls dieser Artikel könnte Ihnen helfen: http://www.bluebytesoftware.com/blog/PermaLink,guid,dd3aff8a-7f8d-4de6-a2e7-d199662b68f4.aspx