C++0x 内存模型和原子操作 (std:::atomic memory order等相关资料)

并行编程的趋势不可阻挡啊,新的c++标准也加入了很多支持。内存模型和 std::atomic 的引入很值得学习吧,看facebook的开源c++库都用了很多c++ 11的特性了。 std::atomic 这些。


网上看到的最详细清楚的解释是,

C++ Concurrency in Action.pdf  一书的第五章

5 The C++ Memory Model and Operations on Atomic Types

对理解 c++ atomic 的memory order很有用处:


这个网页其实也是摘录的书的内容来的,

Memory Ordering for Atomic Operations in C++0x

http://www.developerfusion.com/article/138018/memory-ordering-for-atomic-operations-in


-c0x/


详细解析了 std::atomic 的不同存储模型 ,不同的值与memory order的关系:

有了linux内核的里面内核屏障的概念的话,像下面这样里面比较容易吧。

typedef enum memory_order {

    memory_order_relaxed,   \\ 不指定内存屏障,所以内存操作执行时可能是乱序的。

    memory_order_acquire,   \\ 按照我理解就是插入一个 内存读屏障,保证之前的读操作先一步完成。清空自己cpu上"invalidate queues"  。

    memory_order_release,    \\ 按照我理解就是插入一个 内存写屏障,保证之前的写操作的顺序一定 。清空自己cpu上 的 “ store buffer"


在这之前完成

    memory_order_consume  类似memory_order_acquire,但只对依赖的指定数据起作用。

    memory_order_acq_rel,    \\ 同时插入读写两个屏障。  清空自己cpu上 的 “ store buffer" 和 "invalidate queues"  。

    memory_order_seq_cst    \\\默认的顺序模型。根据  http://en.cppreference.com/w/cpp/atomic/memory_order 这里的说明 (Total sequential ordering requires a full memory fence CPU instruction on all multi-core systems. This may become a performance bottleneck since it forces all memory accesses to propagate to every thread.)  这个会清空所有cpu上的读写同步消息队列 “ store buffer" 和 "invalidate queues"   (参考 http://hi.baidu.com/widebright/item/4e458d447c8bcfe11381daf0 ) 。  memory_order_acq_rel 应该是只清空自己cpu上 的 “ store buffer" 和 "invalidate queues"  。

        这个看上去和x86的lock指令前缀锁总线不太一样。不知道具体怎么实现的。

 

} memory_order;



书上的一个简单的例子。

-----------------------------------------------

#include <atomic>

#include <thread>

#include <assert.h>

 

std::atomic<bool> x,y;

std::atomic<int> z;

 

void write_x_then_y()

{

    x.store(true,std::memory_order_relaxed);             #1

    y.store(true,std::memory_order_release);             #2   //保证 第#1句的x写入在y的写入之前

}

 

void read_y_then_x()

{

    while(!y.load(std::memory_order_acquire));           #3     //保证 y的读取在 第#4句x的读取之前。所以  如果y看到修改后的值,肯定 第#4句看到的也是x的新的值了。

    if(x.load(std::memory_order_relaxed))                #4

        ++z;

}

 

int main()

{

    x=false;

    y=false;

    z=0;

    std::thread a(write_x_then_y);

    std::thread b(read_y_then_x);

    a.join();

    b.join();

    assert(z.load()!=0);                                 #5    //这个肯定通过的了。

}

-----------------------------------------------------------



也说道了内存屏障了

memory fences/barriers

c++ 里面除了上面那些为atomic类型指定明确的存储模型之外,也可以插入 指定的“内存读写屏障 


”的。



书中的其他章节也挺不粗哦的,

7

Designing Data Structures for

Concurrency II: Lock-free

Concurrent Data Structures



相面这个应该是c++的规范文档,解释了为什么要把c++的内存模型定义成这样子。

C++ Atomic Types and Operations

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2427.html#DiscussOrder

Memory Model Rationales

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2176.html



想std:atomic 等特性,应该在行的gcc 和 vc11 里面都有支持了,

C++11 Features in Visual C++ 11

http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx

Status of Experimental C++0x Support in GCC 4.6

http://gcc.gnu.org/gcc-4.6/cxx0x_status.html


像facebook的开源c++库好像这个std::atomic用的很多了,用来实现spinlock 。

可以去参考一下 https://github.com/facebook/folly/tree/master/folly


【转自:http://hi.baidu.com/widebright/item/ee9d66d2be106dba32db904e】

没有更多推荐了,返回首页