4

This question has been asked before but i still don't understand it fully so here it goes.

If i have a class with a property (a non-nullable double or int) - can i read and write the property with multiple threads?

I have read somewhere that since doubles are 64 bytes, it is possible to read a double property on one thread while it is being written on a different one. This will result in the reading thread returning a value that is neither the original value nor the new written value.

When could this happen? Is it possible with ints as well? Does it happen with both 64 and 32 bit applications?

I haven't been able to replicate this situation in a console

4

2 回答 2

3

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

我假设您的意思是“没有任何同步”。

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

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

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

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

于 2012-06-24T06:43:36.187 回答
1

这些操作不是原子的,这就是为什么Interlocked类首先存在的原因,具有类似Increment(Int32)和的方法Increment(Int64)

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

于 2012-06-24T06:47:51.630 回答