C#volatile双

时间:2009-02-10 10:10:37

标签: c# .net volatile

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

public class MyThreadedClass
{
    volatile VolatileDouble voldub;
}

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

4 个答案:

答案 0 :(得分:16)

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

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

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

答案 1 :(得分:5)

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

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

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

答案 2 :(得分:3)

您只是声明引用不是实例的易失性,因此无法解决问题。

答案 3 :(得分:0)

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

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

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