【问题标题】:Writing to adjacent array elements from different threads?从不同的线程写入相邻的数组元素?
【发布时间】:2011-03-21 16:17:05
【问题描述】:

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

我对编写任意大的结构感兴趣,而不仅仅是原生类型。

注意:

请不要提及虚假分享的性能问题。我很清楚这些,但它们对我的用例没有实际意义。我还意识到从阅读器以外的线程写入的数据的可见性问题。这在我的代码中得到了解决。

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

理论上,编译器也可以在硬件不需要时以这种方式实现内存写入,尽管非常愚蠢。 x86 可以处理单个字节,所以这基本上不是问题,但我试图弄清楚它是否存在任何奇怪的极端情况。更一般地说,我想知道从不同线程写入数组的相邻元素是否仍然是一个实际问题,或者主要只是一个仅适用于晦涩/古老的硬件和/或非常奇怪的编译器的理论问题。

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

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

【问题讨论】:

  • 那我可能不明白你在问什么。您想知道将 DWORD 写入地址0x08450380 是否会影响除0x084503800x08450383 之外的任何内存位置?如果可能的话,我会非常担心。
  • @Jim:实际上至少在一些(旧的)架构上是可能的。一些架构不能以单个字节的粒度写入。我不知道这方面的细节,但我知道,在某些 DEC alpha 上,您不能安全地从不同线程写入相邻字节,因为内存写入只能以字粒度进行。要理解这一点,请考虑尝试从不同线程写入同一字节的相邻位。您必须读入一个完整的字节,进行一些操作,然后再写回一个完整的字节。
  • 我不知道,你在追鬼。是的,像 Alpha 和 Itanium 这样的内核有糟糕的内存模型。这就是我们不再使用它们的原因。
  • 不确定您到底想要做什么,但是通过不同的内核写入相同的缓存行会导致性能损失。查找“虚假共享”。一般来说,您不希望不同的内核(尤其是 w/不同的 L1 缓存)修改相同的缓存行(即“写入相邻的数组元素”)
  • @bestsss:请重新阅读问题。我说过我知道这个问题。为了澄清,对相邻元素的写入将很少发生,只要它们是正确的,我不在乎它们是否效率低下。 (但是,对相距较远的元素的写入会更频繁,并且性能在这里很重要,因此锁定每次写入并不是一个好的选择。)

标签: multithreading asynchronous thread-safety x86


【解决方案1】:

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

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

【讨论】:

  • 能否请您详细说明第二段(“操作系统内核中的错误或未保留所需寄存器的中断处理程序”)?谢谢。
  • @aix:假设您的代码使用 EDI 作为目标索引。写入之间出现中断,中断处理程序会破坏 EDI 的值——不保留它。如果操作系统内核的线程上下文切换中存在错误,也会发生同样的事情。诚然,这两种情况发生的可能性都相当小。关键是,一旦您处理的不仅仅是自己的代码,任何事情都可能发生。
【解决方案2】:

是的,当然,写一个跨越 CPU 缓存行边界的错位字不是原子的。

【讨论】:

  • 请看我的编辑:原子性与单词撕裂有什么关系?
  • 占用多个总线周期(撕裂)的内存更新根据定义不是原子的。我不知道是否有 CPU 架构对不涉及撕裂的原生单词进行非原子更新。大概吧。
  • 我认为撕裂或其他东西可能有两种定义。我认为这意味着同时写入相邻但不重叠的内存地址不一定安全。
  • 在您的问题中提供良好的参考链接,以便每个人都在谈论同样的事情。
  • 我愿意,但谷歌在这个主题上产生的绝大多数是旧论坛帖子、民间传说等。我实际上希望这个问题能带来一些好的参考,因为如果他们'在外面,我肯定找不到他们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-07
  • 1970-01-01
相关资源
最近更新 更多