MSDN 指出:
其他类型(包括
、long
、ulong
和double
)以及用户定义类型的读取和写入不需要是原子的。decimal
C# 7.0 规范草案 - 变量 - 9.6 变量引用的原子性
Volatile.Write(Double, Double)
可以作为原子操作吗?如果是这样如何保证?
在一个线程中执行
Volatile.Write(ref mydouble, value);
并在另一个线程中执行 Volatile.Read(ref mydouble)
(其中 mydouble
具有 double
类型)是否安全?
这是一个普遍问题。另一个问题 - 在这种特殊情况下我应该做什么:
不,Volatile 不是原子的,并且在 SMP(>1 个处理器)系统中这样假设是不安全的。在单处理器机器上是安全的。
除非您真的需要性能,否则您可能需要
Interlocked
,无论是Interlocked.Exchange
还是Interlocked.Read
。
Volatile
类的文档(和/或实现)已更新,现在声明:
Volatile类还提供了一些64位类型的读写操作,例如Int64和Double。即使在 32 位处理器上,此类 64 位内存上的易失性读取和写入也是原子的,这与常规读取和写入不同。
因此 64 位值上的
Volatile.Read
和 Volatile.Write
实际上是原子的,即使在 32 位系统上也是如此。
但是,请注意,使用 Volatile
类执行的读取和写入与使用
volatile
字段执行的读取/写入不同。因此,访问 64 位 volatile
字段 不是原子,而使用
Volatile
类 是原子。 来自
volatile
(关键字)文档:其他类型(包括 double 和 long)不能标记为 volatile,因为不能保证对这些类型的字段的读取和写入是原子的。要保护对这些类型字段的多线程访问,请使用 Interlocked 类成员或使用 lock 语句保护访问。
有趣的是,这里没有提到
Volatile
类的原子访问,我个人认为这部分文档有点过时了。