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)如下:
| 枚舉值 | 中文名 | 簡(jiǎn)要說(shuō)明 |
|---|---|---|
| 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)的保證:所有線程中看起來(lái)像是全局有序執(zhí)行 |
簡(jiǎn)明圖解理解(線程內(nèi)操作順序)
- relaxed: 無(wú)序(性能最好,但易出錯(cuò))
- acquire: 不能把后面的操作移到前面
- release: 不能把前面的操作移到后面
- acq_rel: 二者兼具
- seq_cst: 所有線程觀察到的執(zhí)行順序一致
常見(jiàn)用法示例對(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); // 原子讀,不保證看到更新
獲取 / 釋放語(yǔ)義:典型鎖實(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 語(yǔ)義:保證看到的 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é)
| 序名 | 用途 | 是否有序 | 性能 | 說(shuō)明 |
|---|---|---|---|---|
| relaxed | 最快的,不同步 | ? | ?????? | 僅原子性,無(wú)順序 |
| 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)紅問(wèn)題分析
今天在寫 C++ 代碼的時(shí)候用上 C++11 的特性,然后發(fā)現(xiàn) VSCode 雖然可以編譯通過(guò),但是會(huì)在相應(yīng)位置報(bào)紅,這是怎么回事呢?下面小編給大家?guī)?lái)了解決方法,一起看看吧2021-09-09
C++深入探究類與對(duì)象之友元與運(yùn)算符重載
友元就是讓一個(gè)函數(shù)或者類,訪問(wèn)另一個(gè)類中的私有成員;打個(gè)比方,這相當(dāng)于是說(shuō):朋友是值得信任的,所以可以對(duì)他們公開一些自己的隱私,運(yùn)算符重載的實(shí)質(zhì)就是函數(shù)重載或函數(shù)多態(tài),運(yùn)算符重載是一種形式的C++多態(tài),目的在于讓人能夠用同名的函數(shù)來(lái)完成不同的基本操作2022-04-04
使用C語(yǔ)言計(jì)算長(zhǎng)方體的表面積和體積
這篇文章主要給大家介紹了關(guān)于如何使用C語(yǔ)言計(jì)算長(zhǎng)方體的表面積和體積的相關(guān)資料,在C語(yǔ)言中,我們可以使用乘法運(yùn)算符(*)來(lái)進(jìn)行乘法運(yùn)算,并將結(jié)果保存在一個(gè)變量中,需要的朋友可以參考下2023-10-10
Qt創(chuàng)建SQlite數(shù)據(jù)庫(kù)的示例代碼
本文主要介紹了Qt創(chuàng)建SQlite數(shù)據(jù)庫(kù)的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05
C語(yǔ)言sizeof與字符串處理與動(dòng)態(tài)內(nèi)存分配及main函數(shù)參數(shù)詳解
這篇文章主要介紹了C語(yǔ)言字符串處理函數(shù)、sizeof、動(dòng)態(tài)內(nèi)存分配函數(shù)、main函數(shù)參數(shù)問(wèn)題,static在修飾變量的時(shí)候,如果是修飾全局變量,則跟全局變量功能一樣,通過(guò)示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07

