2013-01-15 127 views
3

.NET DateTime线程安全吗?我并不担心如果操作返回不正确的值,我唯一担心的是:如果不同步DateTime对象将被损坏。.NET DateTime线程安全吗

+0

您是否只是从多个线程中读取它?或者你是否将一个'DateTime'字段分配给多个线程?第二个是不安全的。 – CodesInChaos

+0

是的,我正在从多个线程分配DateTime。在这种情况下它会抛出异常吗?或者唯一的缺点是我们无法预测哪个线程的分配操作执行最新? – user632942

+2

这不安全。基础值很长,在32位操作系统上它们不是原子的。 –

回答

11

读取和写入DateTime字段不是原子的(至少在32位系统上)。

  • 如果您从多个线程同时分配到同一个属性,则可能会损坏它。

  • 如果您从一个线程读取并从另一个线程写入,则读取线程可能会损坏值。

  • 从多个线程读取,同时没有写入线程是安全的。

基本上在同一时间从多个线程中使用时为DateTime的两个32位半部可能包含不同年龄的值。

您可以混合使用两次写入。一次写入的高32位部分,另一次写入的低32位部分。

作为一种替代方法,您可以在该字段中使用Int64,并使用ThreadInterlocked的原子方法对其进行处理。然后使用new DateTime(ticks)dateTime.Ticks转换为DateTime

MSDN说:

此类型的所有成员都是线程安全的。似乎修改实例状态的成员实际上会返回一个使用新值初始化的新实例。与任何其他类型一样,对包含此类型实例的共享变量的读写操作必须使用锁保护,以确保线程安全

在所有硬件平台上分配此类型的实例不是线程安全的,因为该实例的二进制表示可能太大而无法在单个原子操作中分配。

+0

但DateTime是不可变的,所以它的字段永远不会改变。或者我错过了什么? – Robert

+1

@Robert在不可变的结构中,不能单独修改字段。但是你可以替换一个变量的内容。这是更换操作本质上复制所有字段。这个替换不一定是原子的。这与不存在替换操作的不可变值类型不同,因为重新分配变量只会复制引用而不是内容。 – CodesInChaos

+1

您可能想使用DateTime.FromBinary(longValue)和dateTime.ToBinary()来代替使​​用Ticks。该值仍然适合于Int64,它将保留Kind属性。 –

6

DateTime是一个不可变的值类型(结构)。您无法在创建后更改实例。

它不会被损坏,并且是线程安全的。

如果要更改一个DateTime变量从多个线程(编写或读/写),您需要同步 - 因为这操作线程安全的。