【问题标题】:Is nullable double and decimal update atomic on x64 system?x64 系统上可空的双精度和十进制更新是原子的吗?
【发布时间】:2012-11-14 03:33:54
【问题描述】:

在大多数情况下,64 位系统上的 doubledecimal 类型更新是原子操作,因为这些类型是 64 位的。 (十进制是 128 位,所以这是错误的,感谢 cmets)

但是当我在 64 位系统上更新 double?decimal? 类型时,它会是原子的吗? double?decimal?的大小是多少

我了解原子性无法保证,但我仍然对此类更新在一般情况下是否为原子性感兴趣。

【问题讨论】:

  • 在讨论原子性的任何情况下,关键什么是保证。如果(如您所说)不能保证原子性,那么坦率地说这就是讨论的结束。任何过去没有意义和无关紧要的东西:你不能相信它,所以不要使用它。
  • .NET 中的 Decimal 是 128 位,而不是 64 位。因此,在 64 位系统上更新 decimal不是原子的。
  • 从技术上讲,即使更新到 double 也无法保证。我可能会使用Interlocked 来谈甚至是那个 - 或者lock 等等。
  • @MarcGravell 不同意。使用特定操作系统和特定框架版本和特定应用程序在我的服务器上保证原子性。如果这是我要使用应用程序的唯一场景,为什么不从原子性中受益?
  • @javapowered 是谁给你保证的?您不会在语言规范中找到它。你的意思是:“我推断这没问题” - 那是不是保证

标签: c# atomic


【解决方案1】:

在大多数情况下,64 位系统上的 double 和 decimal 类型更新是原子操作,因为这些类型是 64 位的。

不,decimal 是 128 位开始的。另请注意,在 64 位 计算机 上运行并不一定意味着您正在运行 64 位 CLR。不清楚这里的“系统”是什么意思。

所以你甚至不应该假设decimal 具有原子性。即使在 64 位 CLR 上,我也不想依赖 double 的原子性,部分原因是它依赖于对齐。 C# 规范明确指出(C# 4 规范的第 5.5 节):

其他类型的读取和写入,包括 long、ulong、double 和 decimal,以及用户定义的类型,不保证是原子的。

所以这使得可以为空的一面有点毫无意义,但是......

但是当我更新双重?和十进制?在 64 位系统上输入会是原子的吗?双倍的尺寸是多少?和十进制?

Nullable<T> 基本上是一个T 字段和一个bool 字段。因此double 的存储空间将超过 64 位,decimal 的存储空间将超过 128 位。确切的存储很可能取决于上下文,但基本上我不会期望这些类型的操作具有原子性。

正如其他人所说,您几乎肯定不想依赖任何没有保证的东西。就个人而言,我几乎总是尽量避免一般的无锁编码。尝试使用 CLR/BCL 团队提供并被证明是安全的更高级别的抽象。

【讨论】:

  • “我个人几乎总是尽量避免使用无锁编码。” - 破坏运动 ;p(那是舌头在脸颊上;当我深入研究无锁时,我会先喝一杯浓咖啡)
  • 我很好奇,如果您在 x86 CPU 上运行,作为 64 位进程,64 位值类型/结构是原子写入的吗? C# 规范故意宽松,但我不明白为什么在 64 位 x86 上下文中它不是原子的。
  • 对不起decimal。好的,在我的系统上(HP DL360p-Gen8、Windows Server 2008 R2、.NET Framework 4.5)double 更新是原子的。 double? 更新不是原子的?我只需要知道我的特定配置上是如何工作的。我不需要便携性,我需要速度。因为速度 = 我的钱,便携性 = 没有。
  • 我也在我的系统中使用double? 非常密集,没有任何锁。因为double? 类型超过 64 位,所以它不能是原子的,对吧?我只是想知道我的系统是如何工作的,没有任何问题。有没有机会让double? 更新原子?可能我只需要编写测试...
  • 鉴于 long、ulong、double 和 decimal 的读取和写入不是原子的,当您尝试在多个线程中同时读取和写入它们时会发生什么情况不加锁我>?你真的能读出无意义的值或完全读/写失败(导致立即异常)吗?
【解决方案2】:

我了解原子性无法保证

就是这样。无法保证。

如果这样的更新在一般情况下是原子的,我仍然感兴趣。

无法保证。

就像Marc said

【讨论】:

  • 我了解到,使用 HP DL360p-Gen 8、Windows Server 2008 R2 和 .NET Framework 4.5 原子性是有保证的。这是我唯一需要的场景。
  • @javapowered - 这与您在问题中描述的相去甚远,并且仍然保证。它似乎以原子方式工作,但事实并非如此。
  • 当然在 this 配置上是有保证的。您将无法在 this 配置上以 not 原子方式运行它。
  • @javapowered - 你在说什么? decimal 是 128 位 - 对它的操作不能在 64 位架构上是原子的。你究竟从哪里得到这个保证?谁来的?
  • 我说的是 64-it 类型,例如 double。我在最初的问题中犯了一个错误。
【解决方案3】:

C# 规范允许将一个 64 位变量写成两个 32 位变量。

C# 语言保留写长的权利 相当于写入两个整数,一个接一个,并且在 练习一些芯片确实以这种方式实现它

查看更多关于 Eric Lippert here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-23
    • 2017-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    相关资源
    最近更新 更多