C++內(nèi)存序memory_order的具體操作
C++ 原子操作提供 6種內(nèi)存序(memory_order),分別控制編譯器和 CPU 如何對(duì)內(nèi)存操作進(jìn)行重排序優(yōu)化,確保并發(fā)程序在多線程之間的行為可控、正確。
所有內(nèi)存序(memory_order)
C++ 中 std::memory_order
的 6 種選項(xiàng)如下:
枚舉值 | 中文名 | 簡要說明 |
---|---|---|
memory_order_relaxed | 放松序 | 不保證任何順序,只保證原子性 |
memory_order_consume | 消費(fèi)序(已廢棄趨勢(shì)) | 數(shù)據(jù)依賴同步,僅限依賴關(guān)系(不推薦使用) |
memory_order_acquire | 獲取序 | 保證本線程之后的操作不會(huì)被重排到原子操作前 |
memory_order_release | 釋放序 | 保證本線程之前的操作不會(huì)被重排到原子操作后 |
memory_order_acq_rel | 獲取 + 釋放序 | 同時(shí)保證 acquire + release 的效果,適用于 read-modify-write 操作 |
memory_order_seq_cst | 順序一致性(默認(rèn)) | 最強(qiáng)的保證:所有線程中看起來像是全局有序執(zhí)行 |
簡明圖解理解(線程內(nèi)操作順序)
- relaxed: 無序(性能最好,但易出錯(cuò))
- acquire: 不能把后面的操作移到前面
- release: 不能把前面的操作移到后面
- acq_rel: 二者兼具
- seq_cst: 所有線程觀察到的執(zhí)行順序一致
常見用法示例對(duì)比
默認(rèn)順序一致性memory_order_seq_cst
#include <atomic> std::atomic<int> x{0}; // 初始化為 0 x.store(10); // store (默認(rèn) seq_cst) int v = x.load(); // load (默認(rèn) seq_cst)
順序一致性:多線程中所有原子操作全局有序,易于理解但開銷較大。
放松序 memory_order_relaxed
#include <atomic> std::atomic<int> x{0}; // 初始化為 0 // 線程 A x.store(10, std::memory_order_relaxed); // 原子寫,不保證順序 // 線程 B int value = x.load(std::memory_order_relaxed); // 原子讀,不保證看到更新
獲取 / 釋放語義:典型鎖實(shí)現(xiàn)方式
#include <atomic> std::atomic<bool> flag{false}; // 默認(rèn)未設(shè)置 // 線程 A:寫線程 data = 123; // 假設(shè) data 是共享變量 flag.store(true, std::memory_order_release); // 發(fā)布 data 已準(zhǔn)備好 // 線程 B:讀線程 if (flag.load(std::memory_order_acquire)) { // 這里看到 flag == true // 根據(jù) acquire 語義:保證看到的 data = 123 std::cout << data << std::endl; }
這就是經(jīng)典的 “寫線程 release,讀線程 acquire” 搭配,確保讀線程看到完整寫入的數(shù)據(jù)。
atomic_flag使用場(chǎng)景建議的 memory_order
操作類型 | 推薦的 memory_order |
---|---|
flag.test_and_set | std::memory_order_acquire |
flag.clear | std::memory_order_release |
小結(jié)
序名 | 用途 | 是否有序 | 性能 | 說明 |
---|---|---|---|---|
relaxed | 最快的,不同步 | ? | ?????? | 僅原子性,無順序 |
acquire | 用于加鎖 | ?(后有序) | ???? | 加鎖讀 |
release | 用于解鎖 | ?(前有序) | ???? | 解鎖寫 |
acq_rel | 讀寫同時(shí) | ? | ?? | 用于 fetch_add 等 |
seq_cst | 最強(qiáng)順序保證 | ??? | ?? | 默認(rèn)值,全局有序 |
consume | 基本棄用 | ? | ? | 不推薦 |
到此這篇關(guān)于C++內(nèi)存序memory_order的具體操作的文章就介紹到這了,更多相關(guān)C++ memory_order內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Qt圖片繪圖類之QPixmap/QImage/QPicture詳解
這篇文章主要為大家詳細(xì)介紹了Qt圖片繪圖類中QPixmap、QImage和QPicture的使用方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-03-03解決 VSCode 編寫 C++11 代碼報(bào)紅問題分析
今天在寫 C++ 代碼的時(shí)候用上 C++11 的特性,然后發(fā)現(xiàn) VSCode 雖然可以編譯通過,但是會(huì)在相應(yīng)位置報(bào)紅,這是怎么回事呢?下面小編給大家?guī)砹私鉀Q方法,一起看看吧2021-09-09C++深入探究類與對(duì)象之友元與運(yùn)算符重載
友元就是讓一個(gè)函數(shù)或者類,訪問另一個(gè)類中的私有成員;打個(gè)比方,這相當(dāng)于是說:朋友是值得信任的,所以可以對(duì)他們公開一些自己的隱私,運(yùn)算符重載的實(shí)質(zhì)就是函數(shù)重載或函數(shù)多態(tài),運(yùn)算符重載是一種形式的C++多態(tài),目的在于讓人能夠用同名的函數(shù)來完成不同的基本操作2022-04-04Qt創(chuàng)建SQlite數(shù)據(jù)庫的示例代碼
本文主要介紹了Qt創(chuàng)建SQlite數(shù)據(jù)庫的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05C語言sizeof與字符串處理與動(dòng)態(tài)內(nèi)存分配及main函數(shù)參數(shù)詳解
這篇文章主要介紹了C語言字符串處理函數(shù)、sizeof、動(dòng)態(tài)內(nèi)存分配函數(shù)、main函數(shù)參數(shù)問題,static在修飾變量的時(shí)候,如果是修飾全局變量,則跟全局變量功能一樣,通過示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07