【问题标题】:Why can't Datetime object be volatile in c#? [duplicate]为什么 Datetime 对象在 c# 中不能是 volatile 的? [复制]
【发布时间】:2018-10-29 10:33:58
【问题描述】:

我可以想到一些用例,在这些用例中,让 DateTime 对象成为原子对象会非常有用。从语言设计的角度来看,不使 DateTime 易变的优点是什么?

【问题讨论】:

  • 长期使用锁是唯一可靠的方法。 Volatile 仅关闭可能导致其他问题的编译器优化。在多任务甚至多线程场景中遇到的问题。 DateTime 可能一开始就没有那些编译器优化。所以关闭它们是没有意义的。

标签: c# datetime volatile


【解决方案1】:

volatile 关键字不保证原子性。 Atomicity is guaranteed for all data types of 32-bits or fewer,带或不带关键字。

volatile 关键字的目的是确保所有线程都在查看变量的同一个副本。您可能会惊讶地发现副本可能不止一个:它们可以保存在主内存中,正如您所期望的那样,也可以保存在一个或多个级别的 CPU 缓存或 CPU 寄存器中。

当您使用volatile 关键字时,编译器会发出一些额外的指令(“memory barriers”)并跳过某些优化以确保所有线程都会看到相同的变量副本。就是这样。

对于大于 32 位的类型,无论如何您都需要 lock,而锁则需要 automatically put those memory barriers in place。所以这些变量不需要 volatile ;用lock 包围访问变量的代码。

【讨论】:

  • 雄辩地解释了为什么我这么喜欢堆栈溢出
  • 可能缺少一点:DateTime 一开始是 64 位类型。在内部,它将“时刻 X”以来的刻度数存储为无符号 Int64。所有其他属性(天、月、周)——甚至是 ToString() 表示——只是对该内部值的一种解释。时刻 X 通常是“Unix 时间的开始”,即 1970 年 1 月 1 日。当然,如果 Int64 不支持该选项,则包含 Int64 的类型不支持该选项。
  • @Christopher:不,对于 .NET DateTime,时代(你称之为“时刻 X”)不是 Unix 时代。 The documentation 很清楚,它从 0001 年 1 月 1 日开始测量。
【解决方案2】:

volatile 关键字只能应用于可原子更新的字段,例如 int、long 引用类型等(请参阅docs 了解更多信息)。

获得所需行为的一种方法是lock statements。这将确保一次只有一个线程可以进入代码的“锁定”部分(也称为关键部分)。

【讨论】:

  • System.Int64 (long) 是不能使用的类型之一。
  • @JonathonChase:volatile 关闭某些编译器优化。您也不能应用它的类型可能一开始就没有应用这些优化。而且您几乎无法关闭,甚至无法选择与之相处?
  • @Christopher 你确定吗? volatile 会停用哪些优化?我的理解是它标记了字段IsVolatile 并让运行时从那里获取它。
【解决方案3】:

有许多编译器和 JiT 编译器优化。例如,如果你写:

{
  int temp = Int32.Parse(input);
  Console.WriteLine(temp);
}

JiT 可能会在调试构建之外思考:“嘿,int 变量实际上并没有在其他任何地方使用。我可以像这样适当地编译它”:

Console.WriteLine(Int32.Parse(input));

它会得到完全相同的结果。”

当人们有这样的嵌套调用时,我经常建议使用临时变量将它们分开,因为我非常清楚 JiT 可以(并且可能会)处理它们。此更改不会对性能产生相关影响,但会提高可读性和可调试性。

编译器也可以反其道而行之。例如,如果您两次调用同一个索引,它实际上会尝试通过添加一个临时变量来保存索引绑定检查。当您期望一个新值时,您实际上可能正在使用本地副本。

但是对于多任务和多线程,任何这样的优化都可能会给您带来很多额外的麻烦。 volatile 会关闭这些优化。但它只能这样做,前提是该类型一开始就有这种优化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-02
    • 1970-01-01
    • 2012-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多