С# изменчивый двойной

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

public class MyThreadedClass
{
    volatile VolatileDouble voldub;
}

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

person johnc    schedule 10.02.2009    source источник


Ответы (4)


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

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

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

person Jon Skeet    schedule 10.02.2009
comment
Вид подозревал, что только ссылка была изменчивой, отсюда и вопрос. Спасибо за подтверждение - person johnc; 10.02.2009
comment
если бы он убедился, что VolatileDouble неизменен, у него не должно быть проблем, верно? - person Jonathan C Dickinson; 10.02.2009
comment
Спасибо также за предложения Interlocked и BitConverter, которые вызвали совершенно новый образ мыслей. - person johnc; 10.02.2009
comment
@Jonathan: Да, я полагаю, что в этом случае все будет в порядке — по крайней мере, с использованием модели памяти .NET 2.0, которая немного сильнее, чем модель памяти ECMA. - person Jon Skeet; 10.02.2009
comment
Извините, что опоздал на вечеринку, но на самом деле это спецификация C#, в которой говорится, что атомарное чтение/запись гарантируется только для типов размером 4 или меньше. CIL дает более сильную гарантию атомарного r/w для размеров указателя или меньше (т.е. 4 байта на x86, 8 байтов на x86_64 (смотря на вас, двойной)). Компилятор компилирует из C# в CIL, поэтому он не может знать, какой будет процессор. Последняя часть головоломки заключается в том, что только типы, которые имеют гарантированные атомарные операции r/w, могут быть объявлены volatile. - person Ordoshsen; 13.05.2020

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

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

Кроме того, блокировка будет лучшим вариантом.

person Marc Gravell    schedule 10.02.2009
comment
123.45ф; Если бы вы не указали на это, я бы не заметил ;) - person johnc; 10.02.2009

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

person Brian Rasmussen    schedule 10.02.2009
comment
Так подозреваю, отсюда и вопрос, спасибо за подтверждение - person johnc; 10.02.2009

Нестабильная документация несколько вводит в заблуждение...

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

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

person mandel    schedule 10.02.2009