这里是不是需要内存屏障“*pEnd_ = v; __sync_synchronize (); ++pEnd_;”?

Posted

技术标签:

【中文标题】这里是不是需要内存屏障“*pEnd_ = v; __sync_synchronize (); ++pEnd_;”?【英文标题】:Is memory barrier needed here "*pEnd_ = v; __sync_synchronize (); ++pEnd_;"?这里是否需要内存屏障“*pEnd_ = v; __sync_synchronize (); ++pEnd_;”? 【发布时间】:2014-01-20 01:00:01 【问题描述】:

pEnd_是一个对象成员,只能在一个线程中添加如下add(),它可能被另一个线程读取。 add() 中需要 __sync_synchronize 吗?

struct Vector 
    ...
    void add(int v) 
        *pEnd_ = v;
        __sync_synchronize(); // is this needed?
        ++pEnd_;
    
private:
    int* pBegin_;
    int* pEnd_;

在另一个线程中迭代。

for (p = pBegin_; p != pEnd_; ++p) 
  // read barrier here may be inserted 
  if (*p) 
    ....
  

【问题讨论】:

屏障是指“互斥体”吗?还是“sync_synchronize”? 如果多个线程同时执行++pEnd_,就会出现竞争条件。 就我而言,只有一个线程可以写。 @ZhouHuabing 但是你需要断言在一个写入过程中没有人读取。 如果您编写由 writer(s) 执行的代码和 reader(s) 的代码,问题可能会更清楚。 【参考方案1】:

至少没有释放内存屏障,您对*pEnd 所做的修改不一定对其他线程可见。所以需要一些东西。

严格来说,不需要__sync_synchronize(),因为它是一个完整的内存屏障。如果您的编译器没有用于仅发布屏障(又称“写屏障”)的内在属性,则完整屏障是合理的。

从表面上看,由于您的pEnd 增量相对于来自其他线程的读取是无序的,因此会导致数据竞争。特定平台可能会保证int* 访问是原子的,并且还可能保证更改在其他线程中以与在此线程中写入的顺序相同的顺序变得可见。因此,在某些平台上,代码是可以的(并且完整的屏障防止写入被重新排序)。这些都不是标准的 C++,它可能是特定于硬件而不是编译器的。

【讨论】:

以上是关于这里是不是需要内存屏障“*pEnd_ = v; __sync_synchronize (); ++pEnd_;”?的主要内容,如果未能解决你的问题,请参考以下文章

我是不是需要内存屏障来访问已完成的线程修改的内存?

内存屏障

谈乱序执行和内存屏障

谈乱序执行和内存屏障

内存屏障 & Memory barrier

为啥需要内存屏障?