Herb Sutter在一次對C++11內(nèi)存模型的演講中提到C++11的內(nèi)存模型井仰,讓C++有了標準獨立于編譯器和平臺線程庫和標準的多線程內(nèi)存控制方式进泼。
咋一看這個句話很奇怪监憎,難道C++98/03及以前的內(nèi)存模型不支持多線程嗎渔期, 用C++03的標準不照樣寫多線程程序镊叁。 其實我忽略了一個事實在B家同學們都是gcc & linux,潛意識posix標準的pthread就是C++的線程庫存团秽,其實還有cl & windows:)
C++標準是基于一個抽象的機器制定的(大部分語言標準應該也是這樣)主胧,它沒有具體的CPU或編譯器。 C++98/03標準沒有對每次讀寫(loads and stores)以及執(zhí)行順序作出規(guī)定习勤,所以無法寫出完全可移植的多線程代碼(能同時支持freebsd踪栋,linux和windows就很不錯了)。C++11標準則在設計上引入了支持多線程的內(nèi)存模型图毕,它規(guī)定了在多線程環(huán)境中內(nèi)存的讀寫的操作以及可能的執(zhí)行順序1夷都。
在cppreference.com上可以看到load和store的原型如下,
T load( std::memory_order order = std::memory_order_seq_cst ) const noexcept;
void store( T desired, std::memory_order order = std::memory_order_seq_cst ) noexcept;
對于memory order多線程環(huán)境中(CPU也是亂序執(zhí)行的)的幾種規(guī)定如下下表,
Value | Explanation |
---|---|
memory_order_relaxed | 對其它讀寫操作沒有同步予颤,只保證本操作是原子的 |
memory_order_consume | load操作囤官,當前線程依賴該原子變量的訪存操作不能reorder到該指令之前,對其他線程store操作(release)可見 |
memory_order_acquire | load操作蛤虐,當前線程所有訪存操作不能reorder到該指令之前党饮,對其他線程store操作(release)可見 |
memory_order_release | store操作,當前線程所有訪存操作不能reorder到該指令之后驳庭,對其他線程load操作(consume)可見 |
memory_order_acq_rel | load/store操作刑顺,memory_order_acquire + memory_order_release |
memory_order_seq_cst | memory_order_acq_rel + 順序一致性(sequential consisten) |
關于memory_order_seq_cst與memory_order_acq_rel,下面這段代碼很直觀的體現(xiàn)了嚷掠,
#include <thread>
#include <atomic>
#include <cassert>
std::atomic<bool> x = {false};
std::atomic<bool> y = {false};
std::atomic<int> z = {0};
void write_x()
{
x.store(true, std::memory_order_seq_cst);
}
void write_y()
{
y.store(true, std::memory_order_seq_cst);
}
void read_x_then_y()
{
while (!x.load(std::memory_order_seq_cst))
;
if (y.load(std::memory_order_seq_cst)) {
++z;
}
}
void read_y_then_x()
{
while (!y.load(std::memory_order_seq_cst))
;
if (x.load(std::memory_order_seq_cst)) {
++z;
}
}
int main()
{
std::thread a(write_x);
std::thread b(write_y);
std::thread c(read_x_then_y);
std::thread d(read_y_then_x);
a.join(); b.join(); c.join(); d.join();
assert(z.load() != 0); // will never happen
}
<p>
知乎上有個G家的stephen w很認真的翻閱了經(jīng)典計算機體系結(jié)構:量化研究方法給了不錯的總結(jié)2,
"SC要求所有內(nèi)存操作表現(xiàn)為(appear)逐個執(zhí)行(任一次的執(zhí)行結(jié)果都像是所有處理器的操作都以某種次序執(zhí)行),每個處理器中的操作都以其程序指定的次序執(zhí)行荞驴。SC有兩點要求:在每個處理器內(nèi)不皆,維護每個處理器的程序次序;在所有處理器間熊楼,維護單一的表征所有操作的次序霹娄。對于寫操作W1, W2, 不能出現(xiàn)從處理器 P1 看來,執(zhí)行次序為 W1->W2; 從處理器 P2 看來鲫骗,執(zhí)行次序卻為 W2->W1 這種情況犬耻。
<p>
參考鏈接