c# - 英特尔架构上的双读原子吗?

标签 c# .net intel

我和我的同事正在就使用 C# .NET 4.0 在英特尔架构上读取 double 的原子性争论不休。他争论说我们应该使用 Interlocked.Exchange 方法来写入 double,但只读取 double 值(在其他线程中)保证是原子的。我的论点是 .NET 不保证这种原子性,但他的论点是在 Intel 架构上这是有保证的(可能不在 AMDSPARC 等上)。

是否有任何英特尔和 .NET 专家对此有一些看法?

Reader 可以读取陈旧的(以前的)值,但不能读取不正确的值(写入前后的部分读取给出垃圾值)。

最佳答案

My colleague and I are having an argument on atomicity of reading a double on an Intel architecture using C# .NET 4.0.

Intel 保证当与 8 字节边界对齐时,8 字节 double 值在读取和写入时是原子的

C# 不保证 double 值与 8 字节边界对齐。

He is arguing that we should use Interlocked.Exchange method for writing into a double, but just reading the double value (in some other thread) is guaranteed to be atomic.

您的同事没有仔细考虑这个问题。互锁操作只是原子相对于其他互锁操作某些时候使用互锁操作没有任何意义;这就像在说,通过十字路口向北行驶的车辆不必遵守红绿灯,因为通过十字路口向西行驶的车辆确实遵守红绿灯。每个人都必须遵守灯光,以免发生碰撞;你不能只做一半。

My argument is that .NET doesn't guarantee this atomicity, but his argument is that on an Intel architecture this is guaranteed (maybe not on AMD, SPARC, etc.).

看,假设这个论点是正确的,但事实并非如此。我们应该得出的结论是,通过错误操作节省的几纳秒是否值得冒这个风险?忘记互锁。 每次都进行完全锁定。跨线程共享内存时,您唯一不应该完全锁定的情况是当您有一个已证明的性能问题时,该问题实际上是由于锁定的 12 纳秒开销造成的。那是当 12 纳秒的惩罚是您程序中最慢的事情并且仍然 Not Acceptable 时,那一天您应该考虑使用低锁解决方案。您的程序中最慢的事情是否占用了 12 纳秒的非竞争锁?不?然后停止争论,花宝贵的时间让程序中需要 超过 12 纳秒的部分更快。

Reader is OK to read a stale (previous) value, but not incorrect value (partial read before and after write giving a garbage value).

不要将原子性与波动性混为一谈。

互锁操作和锁定语句都将构成一个内存屏障,以确保读取或发布最新值。不需要普通的非 volatile 读取或写入;如果碰巧这样做,那你就走运了。

如果您对这些问题感兴趣,我偶尔会被问到一个相关问题,那就是在什么情况下可以取消对整数访问的锁定。我关于该主题的文章是:

关于c# - 英特尔架构上的双读原子吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24731791/

相关文章:

c# - Google Analytics API BatchRequest - 过滤/回调

c# - “检测到无法访问的代码”我已经查看了其他无法访问的代码,但我似乎无法修复我的,halp

.net - 获取 Word 中的当前光标位置 (VSTO)

.net - Microsoft 购买模拟服务不起作用 (805a0194)

.net - f#:已编译程序中的 windows 窗体

x86 - "unscrambled"在这种情况下是什么意思?

c# - 如何使用 Moq 从 IHttpClientFactory 模拟 HTTPClient 并结合 .NET Core 中的 Polly 策略

ubuntu - AMD OpenCL 未将 Intel HD 4000 检测为 GPU 设备

assembly - intel手册中的x86_64 Opcode编码格式

c# - 在 Windows 服务中的 timer_elapsed 事件处理程序中使用异步等待