“双”原子的 Volatile.Read / Volatile.Write 是吗?

问题描述 投票:0回答:2

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
类型)是否安全?

这是一个普遍问题。另一个问题 - 在这种特殊情况下我应该做什么:

  • 2 处理器 Xeon x64 服务器
  • Windows + MS .NET 4.5
  • 从不同线程读取/写入双精度数据
  • 最小的延迟(需要最小,因为我正在编写 HFT 软件)
c# multithreading .net-4.5 volatile thread-synchronization
2个回答
9
投票

不,Volatile 不是原子的,并且在 SMP(>1 个处理器)系统中这样假设是不安全的。在单处理器机器上是安全的。

除非您真的需要性能,否则您可能需要

Interlocked
,无论是
Interlocked.Exchange
还是
Interlocked.Read


0
投票

截至 2023 年,

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

类的原子访问,我个人认为这部分文档有点过时了。

    

© www.soinside.com 2019 - 2024. All rights reserved.