C# volatile double
Поскольку только ссылочные типы и несколько примитивов (включая float, но не double, я не уверен, почему, я рад услышать, почему) могут быть объявлены как volatile, если я оберну double в класс, а затем объявлю его как volatile (как показано ниже), будет ли свойство double потокобезопасным, как и любое другое volatile, или я все еще должен смотреть на блокировку?
public class MyThreadedClass
{
volatile VolatileDouble voldub;
}
public class VolatileDouble
{
public double Double { get; set; }
}
4 ответа:
Причина, по которой double не может быть объявлен volatile: это 64 бита, что делает его больше, чем размер слова на x86, что предотвращает его от объявления volatile в CLI, если я правильно помню.
С вашим текущим ответом только Ссылка рассматривается как изменчивая. Это означает, что модель памяти всегда будет использовать самую последнюю ссылку, но она все равно может использовать устаревшее значение.
Я бы на вашем месте пошел с блокировкой, но есть один вариант-использовать
Interlocked.Read
и ещеInterlocked.Exchange
действуя на лонгах, в сочетании сBitConverter.Int64BitsToDouble
и ещеBitConverter.DoubleToInt64Bits
. Вы можете инкапсулировать это в структуруVolatileDouble
. (Я бы, наверное, сделал его структурой, а не классом.)
Чтобы работать так, как описано выше, вам нужно иметь его неизменяемым (без задатчика) - возможно, с некоторыми неявными операторами преобразования для удобства. В противном случае люди могли бы изменить значение без изменения (изменчивой) ссылки.
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; } }
Помимо этого-блокировка была бы лучшим вариантом.
Изменчивая документация несколько вводит в заблуждение...
Когда в документации msdn говорится, что он использует наиболее актуальное значение, что это означает??? Я уверен, что в простом значении это не приведет к путанице, но как насчет ссылки, так как Брайан Расмуссен вы просто говорите о ref, а не о фактическом экземпляре (и поэтому интересные данные).
С моей точки зрения использование volatile не является хорошей идеей, и я бы пошел на блокировку, в любом случае эта статья может помочь ты: http://www.bluebytesoftware.com/blog/PermaLink,guid,dd3aff8a-7f8d-4de6-a2e7-d199662b68f4.aspx