2009-02-10 4 views
10

Как только ссылочные типы и несколько примитивов (включая float, но не double, я не уверен, почему, я рад слышать, почему), можно объявить изменчивым, если я оберну в классе затем объявить его изменчивым (как показано ниже), будет ли двойное свойство «читать запись» потоком безопасным, как и любой другой изменчивый, или я должен все еще смотреть на блокировку?C# volatile double

public class MyThreadedClass 
{ 
    volatile VolatileDouble voldub; 
} 

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

ответ

16

Причина, почему двойные не может быть объявлена ​​летучей: это 64 бит, что делает его более, чем размер слова на x86, что предотвращает его от декларируемых летучих в CLI, если я правильно помню.

С вашим текущим ответом только ссылка считается изменчивой. Это означает, что модель памяти будет всегда использовать самую последнюю ссылку, но она все равно может использовать устаревшее значение.

Я бы с блокированием, если бы я тебя, но одна альтернатива заключается в использовании Interlocked.Read и Interlocked.Exchange действует на длинных позиций в сочетании с BitConverter.Int64BitsToDouble и BitConverter.DoubleToInt64Bits. Вы можете инкапсулировать это в структуру VolatileDouble. (Я бы, вероятно, сделал бы это скорее структурой, чем классом.)

+0

Вид подозревала, что только ссылка была нестабильной, поэтому вопрос. Спасибо за подтверждение – johnc

+0

, если он удостоверился, что VolatileDouble неизменен, у него не должно быть проблем, правильно? –

+0

Спасибо также за предложения Interlocked и BitConverter, вызвали новый взгляд на мысли – johnc

5

Чтобы работать, как указано выше, вам нужно будет иметь его неизменяемым (без сеттера) - возможно, с некоторыми неявными операторами преобразования для удобства. В противном случае люди могли бы изменить значение без изменения (изменчивой) ссылки.

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

Помимо этого - блокировка будет лучшим вариантом.

+0

Вы не имеете в виду ни одного сеттера? –

+0

Я делаю; -p (oops!) –

+0

хороший код, но я думаю, что вернусь к блокировке – johnc

3

Вы просто заявляете, что ссылка нестабильна, а не экземпляр, так что это не решит проблему.

+0

Подозревается, поэтому вопрос, спасибо за подтверждение – johnc

0

Летучий документация некоторые как вводить в заблуждение ...

когда документация MSDN говорит, что он использует самые современные значения, что это значит ??? Я уверен, что в простой стоимости это не приводит к путанице, но как насчет ссылки, как Брайан Расмуссен, вы просто говорите о рефрексе не фактический экземпляр (и, следовательно, интересные данные).

С моей точки зрения, используя летучий это не очень хорошая идея, и я бы на замок, в любом случае эта статья может вам помочь: http://www.bluebytesoftware.com/blog/PermaLink,guid,dd3aff8a-7f8d-4de6-a2e7-d199662b68f4.aspx