并行编程的趋势不可阻挡啊,新的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】