Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么可以';t Datetime对象在c#中是否易变?_C#_Datetime_Volatile - Fatal编程技术网

为什么可以';t Datetime对象在c#中是否易变?

为什么可以';t Datetime对象在c#中是否易变?,c#,datetime,volatile,C#,Datetime,Volatile,我可以想到许多用例,其中DateTime对象是原子的非常有用。从语言设计的角度来看,不使DateTime易变有什么好处?volatile关键字只能应用于可原子更新的字段,如int、长引用类型等(有关更多信息,请参阅) 获得所需行为的一种方法是。这将确保一次只有一个线程可以进入代码的“锁定”部分(也称为关键部分)。volatile关键字不能保证原子性,带或不带关键字 volatile关键字的目的是确保所有线程都在查看同一个变量副本。您可能会惊讶地发现可能有多个副本:它们可以像您预期的那样保存在主内

我可以想到许多用例,其中DateTime对象是原子的非常有用。从语言设计的角度来看,不使DateTime易变有什么好处?

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


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

volatile关键字不能保证原子性,带或不带关键字

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

当您使用
volatile
关键字时,编译器将发出两条额外的指令(“”),并跳过某些优化,以确保所有线程都将看到变量的相同副本。这就是它的全部功能


对于大于32位的类型,您无论如何都需要一个
,而锁也可以。所以这些变量不需要volatile;在访问变量的代码周围加上一个
锁。

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

{
  int temp = Int32.Parse(input);
  Console.WriteLine(temp);
}
JiT可能会在调试构建之外思考:“嘿,int变量实际上不在其他任何地方使用。我可以像这样编译它”:

它将产生完全相同的结果。”

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

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


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

System.Int64
(long)是它不能使用的类型之一。@JonathonChase:volatile关闭某些编译器优化。不能应用它的类型可能一开始就没有这些优化。而且你很难关闭它,它甚至不能作为一个选项使用?@Christopher你确定吗?volati需要哪些优化le deactivate?我的理解是,它标记了字段
IsVolatile
,并让运行时从那里获取它。使用锁是长期唯一可靠的方法。Volatile只会关闭编译器优化,这可能会导致其他问题。在多任务甚至多线程场景中,除了这些问题之外,DateTime可能无法解决首先,请不要使用那些编译器优化。因此,关闭它们是没有意义的。我已经雄辩地解释了为什么我喜欢堆栈溢出,所以可能缺少了很多字符:DateTime是一个64位类型的开始。在内部,它将自“矩X”以来的刻度数存储为未签名的Int64。所有其他属性(天、月、周)-即使是ToString()表示法-也只是对该内部值的解释。由于X时刻通常是“Unix时间的开始”,即1970年1月1日。当然,如果Int64不支持该选项,则包含Int64的类型也不支持该选项。@Christopher:不,对于.NET
DateTime
epoch(您称之为“时刻X”)不是Unix时代。很明显,它是从0001年1月1日开始测量的。
Console.WriteLine(Int32.Parse(input));