是否有任何现代的常见 CPU 从不同线程同时写入数组的相邻元素是不安全的?我对 x86 特别感兴趣。您可能会认为编译器不会做任何明显荒谬的事情来增加内存粒度,即使它在技术上符合标准。
我对编写任意大结构的情况感兴趣,而不仅仅是本机类型。
Note:
请不要提及与虚假共享相关的性能问题。我很清楚这些,但它们对于我的用例来说没有实际意义。我还意识到从读取器以外的线程写入的数据的可见性问题。这已在我的代码中解决。
澄清:出现此问题是因为在某些处理器(例如旧的 DEC Alpha)上内存只能在字级寻址。因此,以非字大小增量(例如单个字节)写入内存实际上涉及要写入的字节的读取-修改-写入加上一些相邻的字节在引擎盖下。为了形象化这一点,请考虑写入单个位涉及到什么。您读入字节或字,对整个事物执行按位运算,然后将整个事物写回。因此,您无法从不同线程同时安全地写入相邻位。
从理论上讲,编译器在硬件不需要时以这种方式实现内存写入也是可能的,尽管完全愚蠢。 x86 可以寻址单个字节,所以这基本上不是问题,但我试图弄清楚是否存在任何奇怪的极端情况。更一般地说,我想知道从不同线程写入数组的相邻元素是否仍然是一个实际问题,或者主要只是一个理论问题,仅适用于模糊/古老的硬件和/或非常奇怪的编译器。
另一个编辑:这是一个很好的参考,描述了我正在谈论的问题:
http://my.safaribooksonline.com/book/programming/java/0321246780/threads-and-locks/ch17lev1sec6 http://my.safaribooksonline.com/book/programming/java/0321246780/threads-and-locks/ch17lev1sec6
写入本机大小的值(即 1、2、4 或 8 字节)是原子的(嗯,8 字节仅在 64 位计算机上是原子的)。所以不行。编写本机类型总是会按预期编写。
如果您正在编写多个本机类型(即循环写入数组),那么如果操作系统内核中存在错误或中断处理程序不保留所需的寄存器,则可能会出现错误。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)