[英]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.Read
和Interlocked.Exchange
作用於long,與BitConverter.Int64BitsToDouble
和BitConverter.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.