C # изменчивый двойной - PullRequest
       30

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

10 голосов
/ 10 февраля 2009

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

public class MyThreadedClass
{
    volatile VolatileDouble voldub;
}

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

Ответы [ 4 ]

16 голосов
/ 10 февраля 2009

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

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

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

5 голосов
/ 10 февраля 2009

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

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

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

3 голосов
/ 10 февраля 2009

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

0 голосов
/ 10 февраля 2009

Изменчивая документация вводит в заблуждение ...

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

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

...