簡體   English   中英

C# volatile double

[英]C# volatile double

由於只有引用類型和一些基元(包括 float,但不包括 double,我不確定原因,我很高興聽到原因)可以聲明為 volatile,如果我將 double 包裝在 class 中然后聲明它作為 volatile(如下所示),double 屬性是否會像任何其他 volatile 一樣是“讀寫”線程安全的,還是我仍然應該考慮鎖定?

public class MyThreadedClass
{
    volatile VolatileDouble voldub;
}

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

為什么double不能聲明為volatile的原因:它是64位,這使得它超過x86上的字大小,這可以防止它在CLI中被聲明為volatile,如果我沒記錯的話。

根據您當前的答案,只有參考被視為易失性。 這意味着內存模型將確保它始終使用最新的引用,但它仍然可以使用陳舊值。

如果我是你,我會使用鎖定,但另一種方法是使用Interlocked.ReadInterlocked.Exchange作用於long,與BitConverter.Int64BitsToDoubleBitConverter.DoubleToInt64Bits一起使用。 您可以將其封裝在VolatileDouble結構中。 (我可能會把它變成一個結構而不是一個類。)

要像上面這樣工作,你需要讓它不可變(沒有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; }
}

除此之外 - 鎖定將是最好的選擇。

您只是聲明引用是volatile而不是實例,因此無法解決問題。

易變文檔是一些誤導性的......

當msdn文檔說它使用最新的值是什么意思??? 我確信在一個簡單的值中,這不會導致混淆,但是參考如何,就像Brian Rasmussen,你只是在討論ref而不是實際的實例(因此也是有趣的數據)。

從我的觀點來看,使用volatile不是一個好主意,我會去鎖定,無論如何這篇文章可能對你有所幫助: http//www.bluebytesoftware.com/blog/PermaLink,guid,dd3aff8a-7f8d-4de6- a2e7-d199662b68f4.aspx

你不能制作一個 volatile long 或 double(64 位),但你可以制作一個 volatile int(32 位),並且通過使用兩個 32 位 int,你可以成功地使用位操作來模擬 64 位(經過測試和工作):

public class VolatileLong
{
    private readonly object lockObj = new object();
    private volatile int lo32;
    private volatile int hi32;
    public long Value
    {
        get
        {
            lock (lockObj)
            {
                return ((long)hi32 << 32) | ((long)lo32 & 0xFFFFFFFFL);
            }
        }
        set
        {
            lock (lockObj)
            {
                lo32 = (int)(value & 0xFFFFFFFFL);
                hi32 = (int)((value - ((long)lo32 & 0xFFFFFFFFL)) >> 32);
            }
        }
    }
}

public class VolatileDouble
{
    private readonly VolatileLong vl = new VolatileLong();
    public double Value
    {
        get
        {
            return System.BitConverter.Int64BitsToDouble(vl.Value);
        }
        set
        {
            vl.Value = System.BitConverter.DoubleToInt64Bits(value);
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM