2009-02-10 10 views
10

Comme seuls les types de référence et quelques primitives (y compris float, mais pas double, je ne suis pas sûr de la raison pour laquelle, je suis heureux d'entendre pourquoi) peuvent être déclarées volatiles, si j'enveloppe un double dans une classe alors déclarez-le comme volatil (comme ci-dessous), la propriété double sera-t-elle 'read write' thread sûre comme toute autre volatile, ou devrais-je encore regarder verrouiller?C# volatile double

public class MyThreadedClass 
{ 
    volatile VolatileDouble voldub; 
} 

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

Répondre

16

Raison pour laquelle deux ne peut être déclarée volatile: il est 64 bits, ce qui en fait plus que la taille de mot sur x86, ce qui l'empêche d'être déclarée volatile dans le CLI si je me souviens bien.

Avec votre réponse actuelle, seule la référence est traitée comme étant volatile. Cela signifie que le modèle de mémoire s'assurera qu'il utilise toujours la référence la plus récente, mais qu'il peut toujours utiliser une valeur périmée.

je partirais avec verrouillage si je vous étais, mais une alternative est d'utiliser Interlocked.Read et Interlocked.Exchange agissant sur languit, conjointement avec BitConverter.Int64BitsToDouble et BitConverter.DoubleToInt64Bits. Vous pouvez encapsuler ceci dans une struct VolatileDouble. (Je ferais probablement une structure plutôt qu'une classe.)

+0

Type de soupçonner que seule la référence était volatile, d'où la question. Merci pour la confirmation – johnc

+0

s'il s'est assuré que le VolatileDouble est immuable il ne devrait pas avoir de problèmes, correct? –

+0

Merci également pour les suggestions Interlocked et BitConverter, a déclenché une toute nouvelle voie de pensée – johnc

5

Pour fonctionner comme ci-dessus, vous auriez besoin de l'avoir immuable (pas de setter) - peut-être avec quelques opérateurs de conversion implicites pour plus de commodité. Sinon, les utilisateurs pourraient changer la valeur sans changer la référence (volatile).

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; } 
} 

Au-delà, le verrouillage serait la meilleure option.

+0

Voulez-vous dire pas de setter? –

+0

Je fais ;-p (oups!) –

+0

bon code, mais je pense que je vais revenir à verrouillage – johnc

3

Vous venez de déclarer que la référence est volatile et non l'instance, ce qui ne résoudra pas le problème.

+0

Soupçonné ainsi, d'où la question, merci pour la confirmation – johnc

0

La documentation volatile est une façon trompeuse ...

lorsque la documentation msdn dit qu'il utilise le plus à la valeur de ce jour, qu'est-ce que cela signifie ??? Je suis sûr que dans une valeur simple cela ne mène pas à la confusion, mais qu'en est-il d'une référence, comme Brian Rasmussen vous parlez juste de l'arbitre pas l'instance réelle (et donc les données intéressantes).

De mon point de vue à l'aide volatile n'est pas une bonne idée et j'irais pour la serrure, de toute façon cet article pourrait vous aider: http://www.bluebytesoftware.com/blog/PermaLink,guid,dd3aff8a-7f8d-4de6-a2e7-d199662b68f4.aspx