memory orderhtml
源码变成可执行程序,通常由预编译,编译,汇编,连接。源码重排序通常分为编译期重排序和运行期重排序。node
编译期重排序:编译器在不改变单线程程序的语义的前提下,能够从新安排语句的执行顺序。在不改变程序的语义的前提下,尽量减小寄存器的读取,存储次数,充分复用寄存器的存储值。ios
CPU乱序执行c++
名称 | 语义 |
memory_order_relaxed | Relaxed语义 |
memory_order_consume | Release-Acquire语义 |
memory_order_acquire | Release-Acquire语义 |
memory_order_release | Release-Acquire语义 |
memory_order_acq_rel | Release-Acquire语义 |
memory_order_seq_cst | Sequential consistency语义 |
synchronizes-with、happens-before关系编程
synchronizes-with: 若是线程A存储一个值,而线程B读取该值,那么线程A中的存储和线程B的载入之间存在一种synchronizes-with关系并发
happens-before: 若是一个操做排在另一个操做以前,那么该操做就该发生于另外一个操做以前app
Relaxed语义函数
最宽松的内存操做约定,不会保证修改会不会及时被其余的线程看到,也不对乱序作任何要求性能
relaxed的原子类型操做不参与synchronizes-with关系。ui
不一样变量的relaxed能够被自由的重排,前提它们服从全部约束下的happens-before关系
#include <atomic> #include <thread> #include <assert.h> atomic<bool> x, y; atomic<int> z; void write_x_then_y() { x.store(true, memory_order_relaxed); y.store(true, memory_order_relaxed); } void read_y_then_x() { while (!y.load(memory_order_relaxed)); if (x.load(memory_order_relaxed)) ++z; }int main() { x = false; y = false; z = 0; thread a(write_x_then_y); thread b(read_y_then_x); a.join(); b.join(); assert(z.load() != 0); // z可能等于0 }
Release-Acquire语义Sequential consistency语义
release和acquire老是一块儿使用
release用于写操做,acquire用于读操做
release以前的写操做不容许乱序到release以后, acquire以前的读操做不容许乱序到acquire以前
acquire的修改会及时被release看到
Sequential consistency语义
sequential consistency 至关于 release + acquire 以外,还加上了一个对该操做加上全局顺序的要求
#include <atomic> #include <thread> #include <assert.h> atomic<bool> x, y; atomic<int> z; void write_x() { x.store(true, memory_order_seq_cst); } void write_y() { y.store(true, memory_order_seq_cst); } void read_x_then_y() { while (!x.load(memory_order_seq_cst)); if (y.load(memory_order_seq_cst)) ++z; } void read_y_then_x() { while(!y.load(memory_order_seq_cst)); if (x.load(memory_order_seq_cst)) ++z; } int main() { x = false; y = false; z = 0; thread a(write_x); thread b(write_y); thread c(read_x_then_y); thread d(read_y_then_x); a.join(); b.join(); c.join(); d.join(); assert(z.load() != 0); // z不可能等于0 }
store,load
atomic<bool> x, y; atomic<int> z; void write() { x.store(true, memory_order_relaxed); y.store(true, memory_order_release); // x的值比y先填充值 } void read() { while(!y.load(memory_order_acquire)); // y在等write值得填充 if (x.load(memory_order_relaxed)) { z++; } } int main() { x = false; y = false; z = 0; thread t1(write); thread t2(read); t1.join(); t2.join(); cout << "z: " << z << endl; }
exchage
compare_exchange_weak
bool compare_exchange_weak(T& expected, T val, memory_order sync = memory_order_seq_cst)
NOTE:
1. atomic变量的值与expected进行比较, 若是结果true, 用val更新atomic的值(like store); 若是结果为false, 用atomic的值更新expected的值.
2. 这个函数能得到这个atomic变量的值,而且若是比较的结果是true的话就修改这个值. 整个操做是原子操做,在读取或者修改这个值得瞬间,其余的线程不会修改这个值.
3. memory_order 是否生效也是根据比较的结果,若是结果为true,那么生效,不然不生效
4. compare_exchage_weak容许伪失败(fail spuriously),尽管expected值确实和atomic变量的值相等,仍然会返回false; 这须要使用while操做
#include <iostream> #include <atomic> #include <thread> #include <vector> using namespace std; struct Node { int value; Node *next; }; atomic<Node*> list_head(nullptr); void Append(int val) { Node *p_old_node = list_head; Node *p_new_node = new Node {val, p_old_node}; while (!list_head.compare_exchange_weak(p_old_node, p_new_node)) { p_new_node->next = p_old_node; } } int main() { vector<thread> threads; for (int i = 0; i < 10; i++) { threads.push_back(thread(Append, i)); } for (auto &i : threads) { i.join(); } for (Node *it = list_head; it != nullptr; it = it->next) { cout << it->value << " "; } cout << endl; }
compare_exchange_strong
bool compare_exchange_strong (T& expected, T val, memory_order sync = memory_order_seq_cst)
1. compare_exchange_strong的用法和compare_exchange_weak基本用法都同样
2. compare_exchange_strong不容许伪失败(fail spuriously)
3. compare_exchange_weak的循环结构在某些机器上可能有更好的性能
atomic<int> ai; int tst_val = 4; int new_val = 5; bool exchanged = false; void valsout() { cout << "ai: " << ai << " tst_val: " << tst_val << " new_val: " << new_val << " exchanged: " << boolalpha << exchanged << endl; } int main() { ai = 3; valsout(); //ai = 3, tst_val = 4, new_val = 5, exchanged = false; exchanged = ai.compare_exchange_strong(tst_val, new_val); valsout(); //ai = 3, tst_val = 3, new_val = 5, exchanged = false; exchanged = ai.compare_exchange_strong(tst_val, new_val); valsout(); //ai = 3, tst_val = 3, new_val = 5, exchanged = false; }
参考资料:
[1] http://www.cplusplus.com/reference/atomic/atomic/
[2] <<c++并发编程>>
[3] http://www.cnblogs.com/haippy/p/3252056.html
[4] http://www.cnblogs.com/muhe221/articles/5049474.html