原子读取和写入属性

时间:2012-06-24 06:35:12

标签: multithreading c#-4.0 properties

此问题之前已被问过,但我仍然完全不理解,所以这里就是这样。

如果我有一个带有属性的类(一个不可为空的double或int) - 我可以读取和写入多个线程的属性吗?

我已经读过某个地方,因为双精度数为64字节,所以可以在一个线程上读取一个double属性,而不是在另一个线程上写入。这将导致读取线程返回既不是原始值也不是新写入值的值。

什么时候会发生这种情况?也可以使用整数? 64位和32位应用程序都会发生这种情况吗?

我无法在控制台中复制这种情况

2 个答案:

答案 0 :(得分:3)

  

如果我有一个带有属性的类(一个不可为空的double或int) - 我可以用多个theads读写这个属性吗?

我认为你的意思是“没有任何同步”。

doublelong的大小均为64 (8字节),并且保证以原子方式写入。因此,如果您从具有字节模式ABCD EFGH的值移动到具有字节模式MNOP QRST的值,您可能可能最终看到(来自不同的线程)ABCD QRST或MNOP EFGH。

使用大小为32位或更低的正确对齐值,可保证原子性。 (我不记得看到任何保证值正确对齐,但我相信它们是默认情况下,除非你通过属性强制特定布局。)C#4规范甚至没有提到对齐在第5.5节中涉及原子性:

  

以下数据类型的读写是原子的:bool,char,byte,sbyte,short,ushort,uint,int,float和reference类型。此外,在先前列表中具有基础类型的枚举类型的读取和写入也是原子的。其他类型的读写,包括long,ulong,double和decimal,以及用户定义的类型,不保证是原子的。除了为此目的而设计的库函数之外,不保证原子读 - 修改 - 写,例如在递增或递减的情况下。

此外,原子性与波动性不同 - 因此,如果不采取任何额外的谨慎措施,从一个线程读取可能不会“看到”来自不同线程的写入。

答案 1 :(得分:1)

这些操作不是原子操作,这就是Interlocked类首先存在的原因,使用Increment(Int32)Increment(Int64)等方法。

为了确保线程安全,您应该至少使用此类,如果不是更复杂的锁定(使用ReaderWriterLockSlim,例如,如果您想要同步对属性组的访问)。