为什么Datetime对象不能在c#中出现波动?

时间:2018-05-18 23:59:38

标签: c# datetime volatile

我可以想到一些使用DateTime对象是原子的非常有用的用例。从语言设计的角度来看,有什么优势可以使DateTime不稳定?

3 个答案:

答案 0 :(得分:5)

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。那些变量不需要那么不稳定;围绕使用lock访问变量的代码。

答案 1 :(得分:0)

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

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

答案 2 :(得分:-2)

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

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

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

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

它会有完全相同的结果。“

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

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

但是对于多任务处理和多线程处理,任何此类Optimsiation可能会给您带来大量额外的麻烦。 volatile会关闭那些优化。但它只能这样做,如果类型有优化开始。