2009-02-10 21 views
10

Como solo los tipos de referencia y algunos primitivos (incluido float, pero no el doble, no estoy seguro de la razón por la cual, me alegra saber por qué) pueden declararse como volátiles, si doy un doble en una clase y luego declararlo como volátil (como se muestra a continuación), ¿la propiedad doble será segura para lectura como cualquier otra volátil, o debería seguir buscando el bloqueo?C# volatile double

public class MyThreadedClass 
{ 
    volatile VolatileDouble voldub; 
} 

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

Respuesta

16

Por lo doble no puede ser declarada volátil: es 64 bits, lo que hace que sea más que el tamaño de la palabra en x86, lo que evita que sea declarado volátil en el CLI si no recuerdo mal.

Con su respuesta actual, solo la referencia se considera volátil. Eso significa que el modelo de memoria se asegurará de que siempre use la referencia más reciente, pero aún podría usar un valor obsoleto.

me gustaría ir con bloqueo si fuera tú, pero una alternativa es utilizar Interlocked.ReadInterlocked.Exchange y actuar sobre anhela, en conjunción con BitConverter.Int64BitsToDouble y BitConverter.DoubleToInt64Bits. Puede encapsular esto dentro de una estructura VolatileDouble. (Probablemente lo convertiría en una estructura en lugar de una clase.)

+0

tipo de sospecha de que sólo la referencia era volátil, por lo tanto, la pregunta. Gracias por la confirmación – johnc

+0

si se aseguró de que el VolatileDouble sea inmutable, no debería tener problemas, ¿correcto? –

+0

Gracias también por las sugerencias de enclavamiento y BitConverter, provocó una nueva forma de pensar – johnc

5

Para trabajar como antes, necesitaría tenerlo inmutable (sin setter) - quizás con algunos operadores de conversión implícita por conveniencia. De lo contrario, las personas podrían cambiar el valor sin cambiar la referencia (volátil).

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

Más allá de eso, el bloqueo sería la mejor opción.

+0

¿Quiere decir no setter? –

+0

Lo hago ;-p (¡Uy!) –

+0

buen código, pero creo que volveré a bloquear – johnc

3

Usted está declarando que la referencia no es volátil, por lo que no resolverá el problema.

+0

Sospecha que sí, de ahí la pregunta, gracias por la confirmación – johnc

0

La documentación volátil es de alguna forma engañosa ...

cuando la documentación de MSDN dice que utiliza la mayoría hasta la fecha de valor ¿qué significa ??? Estoy seguro de que en un valor simple esto no lleva a confusión, pero ¿qué pasa con una referencia, como Brian Rasmussen, usted solo está hablando de la referencia, no de la instancia real (y, por lo tanto, de los datos interesantes).

Desde mi punto de vista utilizando volátiles no es una buena idea y me gustaría ir a la cerradura, de todos modos este artículo pueden ayudar: http://www.bluebytesoftware.com/blog/PermaLink,guid,dd3aff8a-7f8d-4de6-a2e7-d199662b68f4.aspx