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 10

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