从不同的线程写入相邻的数组元素?

时间:2011-03-21 16:17:06

标签: multithreading asynchronous thread-safety x86

是否存在任何现代的通用CPU,从不同的线程同时写入数组的相邻元素是不安全的?我对x86特别感兴趣。您可以假设编译器没有做任何明显荒谬的事情来增加内存粒度,即使它在技术上符合标准。

我对编写任意大型结构的情况感兴趣,而不仅仅是本机类型。

注意:

请不要提及有关虚假共享的性能问题。我很清楚这些,但它们对我的用例没有实际意义。我也知道从除读者之外的线程写入的数据的可见性问题。这在我的代码中得到了解决。

澄清:出现这个问题是因为在某些处理器(例如,旧的DEC Alphas)上,内存只能在字级处理。因此,以非字大小增量(例如,单个字节)写入存储器实际上涉及要写入的字节的读 - 修改 - 写入加上一些相邻的字节。要想象这一点,请考虑写入单个位所涉及的内容。你读取了字节或单词,对整个事物执行按位操作,然后将整个事情写回来。因此,您无法安全地从不同的线程写入相邻的位。

理论上,当硬件不需要时,编译器也可以通过这种方式实现内存写入,这在理论上是可行的,尽管非常愚蠢。 x86可以解决单个字节,所以它主要不是问题,但我想弄清楚是否有任何奇怪的角落情况。更一般地说,我想知道从不同的线程写入数组的相邻元素是否仍然是一个实际问题,或者大多数只是理论上只适用于模糊/古老的硬件和/或非常奇怪的编译器。

又一个编辑:这是一个很好的参考,描述了我正在谈论的问题:

http://my.safaribooksonline.com/book/programming/java/0321246780/threads-and-locks/ch17lev1sec6

2 个答案:

答案 0 :(得分:1)

写一个本机大小的值(即1,2,4或8个字节)是原子的(好吧,8个字节在64位机器上只是原子的)。所以不行。编写本机类型将始终按预期编写。

如果您正在编写多个本机类型(即循环编写数组),那么如果操作系统内核中存在错误或者中断处理程序没有保留所需的寄存器,则可能会出错。

答案 1 :(得分:1)

是的,当然,编写一个跨越CPU缓存行边界的错误对齐词并非原子。