【问题标题】:C# volatile doubleC# 易失双
【发布时间】:2017-01-30 19:38:50
【问题描述】:

因为只有引用类型和一些原语(包括浮点数,但不是双精度数,我不确定原因,我很高兴听到为什么)可以声明为易失性,如果我将双精度封装在一个类中然后将其声明为 volatile(如下所示),double 属性是否会像任何其他 volatile 一样是“读写”线程安全的,还是我仍然应该关注锁定?

public class MyThreadedClass
{
    volatile VolatileDouble voldub;
}

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

【问题讨论】:

    标签: c# .net volatile


    【解决方案1】:

    double 不能被声明为 volatile 的原因:它是 64 位,这使得它比 x86 上的字长更大,如果我没记错的话,这会阻止它在 CLI 中被声明为 volatile。

    根据您当前的答案,只有 reference 被视为易失性。这意味着内存模型将确保它始终使用最新的引用,但它仍然可以使用陈旧的值。

    如果我是你,我会选择锁定,但另一种选择是使用 Interlocked.ReadInterlocked.Exchange 作用于多头,并结合 BitConverter.Int64BitsToDoubleBitConverter.DoubleToInt64Bits。您可以将其封装在 VolatileDouble 结构中。 (我可能会把它变成一个结构而不是一个类。)

    【讨论】:

    • 有点怀疑只有参考是不稳定的,因此是这个问题。感谢您的确认
    • 如果他确保 VolatileDouble 是不可变的,他应该没有问题,对吗?
    • 也感谢 Interlocked 和 BitConverter 的建议,引发了一条全新的思路
    • @Jonathan:是的,我相信在那种情况下会没问题 - 至少使用比 ECMA 内存模型稍强的 .NET 2.0 内存模型。
    • 很抱歉迟到了,但实际上它本质上是一个 C# 规范,它规定原子读/写仅在大小为 4 或更小的类型上得到保证。 CIL 对指针大小或更小的指针(即 x86 上的 4 个字节,x86_64 上的 8 个字节(看着你,双倍))提供了更强的原子读/写保证。编译器从 C# 编译为 CIL,因此它无法知道处理器将是什么。最后一个难题是只有保证原子读写操作的类型才能被声明为 volatile。
    【解决方案2】:

    要像上面那样工作,你需要让它不可变(没有设置器)——为了方便起见,可能使用一些隐式转换运算符。否则,人们可以在不更改(易失性)引用的情况下更改值。

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

    除此之外 - 锁定将是最好的选择。

    【讨论】:

    • 123.45f;如果你没有指出,我不会注意到 ;)
    【解决方案3】:

    您只是声明引用是 volatile 而不是实例,所以这不会解决问题。

    【讨论】:

    • 怀疑如此,故问,感谢确认
    【解决方案4】:

    易变的文档有些误导...

    当 msdn 文档说它使用最新值时,这是什么意思???我敢肯定,在一个简单的值中,这不会导致混淆,但是引用呢,正如 Brian Rasmussen 所说,您只是在谈论 ref 而不是实际实例(因此是有趣的数据)。

    从我的角度来看,使用 volatile 不是一个好主意,我会去锁定,无论如何这篇文章可能会对你有所帮助:http://www.bluebytesoftware.com/blog/PermaLink,guid,dd3aff8a-7f8d-4de6-a2e7-d199662b68f4.aspx

    【讨论】:

      猜你喜欢
      • 2023-03-13
      • 1970-01-01
      • 2012-10-04
      • 2012-02-22
      • 1970-01-01
      • 2011-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多