当前位置:  开发笔记 > 编程语言 > 正文

C#volatile双

如何解决《C#volatile双》经验,为你挑选了2个好方法。

因为只有引用类型和一些原语(包括float,但不是double,我不确定原因,我很高兴听到原因)可以声明为volatile,如果我在类中包装double然后声明它作为volatile(如下所示),double属性是'read write'线程安全,就像任何其他volatile一样,还是我还应该看看锁定?

public class MyThreadedClass
{
    volatile VolatileDouble voldub;
}

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

Jon Skeet.. 16

为什么double不能声明为volatile的原因:它是64位,这使得它超过x86上的字大小,这可以防止它在CLI中被声明为volatile,如果我没记错的话.

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

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



1> Jon Skeet..:

为什么double不能声明为volatile的原因:它是64位,这使得它超过x86上的字大小,这可以防止它在CLI中被声明为volatile,如果我没记错的话.

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

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



2> Marc Gravell..:

要像上面这样工作,你需要让它不可变(没有setter) - 为方便起见,可能还有一些隐式转换运算符.否则,人们可以在不更改(volatile)引用的情况下更改值.

public class MyThreadedClass
{
    volatile Box volDouble = 123.45;
}

public class Box 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 box) {
        return box.value; }
    public static implicit operator T?(Box box) {
        return box == null ? new T?() : new T?(box.value); }
    public static implicit operator Box(T value) {
        return new Box(value); }
    public static implicit operator Box(T? value) {
        return value.HasValue ? new Box(value.Value) : null; }
}

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

推荐阅读
可爱的天使keven_464
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有