读取和写入一个类型为double的变量保证在64位英特尔处理器上是原子的吗?

时间:2014-06-27 09:40:17

标签: c# .net multithreading

我有一台运行64位处理器的64位机器,但我的应用程序是32位。读取或写入双重保证是原子的吗?我说的是作业和阅读。 32位进程如何影响此过程?当其他线程在给定的规范中写入时,读者是否可以从double读取部分值?

1 个答案:

答案 0 :(得分:3)

没有。 double 可以轻松跨越L1缓存线边界,需要多个总线周期将两个部分粘合在一起。在C#中一个非常现实的问题是,32位CLR仅提供4的对齐保证。

这些未对齐的访问不仅不是原子的,而且由于处理器需要进行混洗,它们也很昂贵。使用double的代码可以有3个不同的时序,如果双重恰好与8对齐,则速度快,当它未对齐为4但仍然在L1缓存行内时速度慢两倍,当它在一个未对齐时超过三倍缓存行。当垃圾收集器压缩堆并移动double时,这样的程序可以随机碰到其中一种模式。 非常警惕这一点,合成测试程序很容易错过这种失败模式。

perf问题是正常情况下更快地在大对象堆中分配double []的核心原因。 LOH提供8对齐保证。对象> = 85,000字节的正常规则是,对于32位模式的double [],它是8,000字节(数组中有1000个元素)。

如果需要原子性保证,必须使用Interlocked.Exchange()。而且我应该发布免责声明,原子性是一个非常弱的保证,并且在需要时无法替代正确的锁定。