C++八股 —— 原子操作

文章目錄

    • 1. 什么是原子操作
    • 2. 原子操作的特點
    • 3. 原子操作的底層原理
    • 4. 內存序
      • 內存屏障
    • 5. 原子操作和互斥鎖的對比
    • 6. 常用的原子操作
    • 7. 相關問題討論

參考

  • C++ atomic 原子操作_c++ 原子操作-CSDN博客
  • DeepSeek

1. 什么是原子操作

原子操作(Atomic Operations)是不可分割的操作,保證在多線程環境中執行時不會被中斷,避免數據競爭(Data Race)。即:原子操作要么完全執行,要么完全不執行,不會在執行期間被其他線程操作干擾。

C++11引入<atomic>頭文件,提供std::atomic<T>模板類,支持對基本類型(如intbool、指針)的原子操作。

2. 原子操作的特點

  • 無鎖(Lock-Free): 原子操作通常由硬件指令(如CAS,LL/SC)實現,無需顯式加鎖。
  • 線程安全: 保證對變量的讀寫操作在多線程環境下的正確性。
  • 輕量級: 適合簡單操作(如計數器、標志位),性能通常高于互斥鎖。

示例:

#include <atomic>
std::atomic<int> counter(0);void increment() {counter.fetch_add(1, std::memory_order_relaxed); // 原子遞增
}

3. 原子操作的底層原理

原子操作的實現依賴于硬件指令,例如:

  • CAS(Compare-And-Swap):通過比較內存中的值與預期值,若匹配則更新為新值。

    bool compare_exchange_strong(T& expected, T desired) {if (current == expected) {current = desired;return true;} else {expected = current;return false;}
    }
    
  • LL/SC(Load-Linked/Store-Conditional):在特定地址上標記“監視”,若未被其他線程修改則寫入。

這些指令保證操作的原子性,但不同硬件(x86、ARM)的實現差異較大。例如:

  • x86:通過LOCK前綴指令(如LOCK XCHG)實現原子操作。
  • ARM:依賴LL/SC指令實現無鎖原子操作。

原子操作的局限性

  • ABA問題:線程A讀取值A,線程B將值改為B后又改回A,導致A的CAS誤判無變化。
    解決方案:使用帶版本號的原子變量(如std::atomic<std::pair<T, uint64_t>>)。
  • 適用范圍:僅適用于基本類型(如intbool、指針)。復雜類型需使用std::atomic_flag或互斥鎖。

4. 內存序

內存序(Memory Order)定義了原子操作之間的可見性順序約束,確保多線程環境下的內存訪問符合預期。以下問題可能導致指令順序變化:

  • 編譯器重排:編譯器優化可能導致指令順序變化。
  • CPU重排:現代CPU的亂序執行機制(如Store Buffer、Invalidate Queue)可能打亂指令順序。
  • 緩存一致性:不同核心的緩存狀態可能導致內存視圖不一致。

C++提供6種內存序,分為三類:

內存序描述
順序一致性(Sequential Consistency)
memory_order_seq_cst最嚴格,保證全局順序一致,性能較低。默認選項。
獲取-釋放(Acquire-Release)
memory_order_acquire保證后續讀操作不會重排到該操作之前(用于“獲取”同步)。
memory_order_release保證前面的寫操作不會重排到該操作之后(用于“釋放”同步)。
memory_order_acq_rel同時包含acquire和release語義(用于讀-改-寫操作)。
寬松(Relaxed)
memory_order_relaxed僅保證原子性,無順序約束(適用于計數器等無需同步的場景)。
memory_order_consume依賴順序(較弱的acquire,C++17后不推薦使用)。

典型場景:

生產者-消費者模型:

// 生產者線程
data = ...; // 生產數據
flag.store(true, std::memory_order_release); // 發布數據// 消費者線程
while (!flag.load(std::memory_order_acquire)); // 獲取數據
use_data(data); // 安全使用數據

內存屏障

1. 內存屏障的作用

內存屏障是硬件或編譯器級別的指令,用于強制限制內存操作的執行順序,分為兩類:

  • 編譯器屏障:阻止編譯器重排指令(如asm volatile("" ::: "memory"))。
  • 硬件屏障:阻止CPU重排內存訪問(如x86的MFENCE、ARM的DMB)。

2. C++內存序與內存屏障的映射

  • std::atomic_thread_fence():顯式插入內存屏障。

    std::atomic_thread_fence(std::memory_order_acquire); // 插入讀屏障
    
  • 隱式屏障:原子操作的內存序參數隱式插入屏障:

    a.store(1, std::memory_order_release); // 隱式插入Store屏障
    

3. 內存屏障的實際案例

示例:無鎖隊列的入隊操作

// 生產者線程
Node* new_node = new Node(data);
new_node->next.store(head, std::memory_order_relaxed);
head.store(new_node, std::memory_order_release); // 插入寫屏障,確保new_node初始化完成后再更新head// 消費者線程
Node* local_head = head.load(std::memory_order_acquire); // 插入讀屏障,確保讀取到最新的head
if (local_head != nullptr) {// 安全操作local_head->next
}

5. 原子操作和互斥鎖的對比

特性原子操作互斥鎖(如std::mutex)
實現方式硬件指令(如CAS)實現無鎖操作。通過操作系統內核的鎖機制(可能涉及上下文切換)。
性能低競爭時性能高,高競爭時可能自旋。高競爭時可能更高效(線程休眠)。
適用場景簡單操作(如計數器、標志位)。復雜操作或需要保護多個變量/代碼塊。
內存序復雜性需顯式指定內存序,易出錯。隱式保證順序一致性,更簡單。
死鎖風險無。需避免死鎖(如加鎖順序不一致)。
ABA問題可能發生(需配合版本號解決)。無。

選擇建議:

  • 使用原子操作:需要高性能的簡單操作,且能正確處理內存序。
  • 使用互斥鎖:保護復雜邏輯或臨界區較長時,簡化代碼并減少錯誤。

6. 常用的原子操作

  • load:讀取原子變量的值

    std::atomic<int> a(1);
    int value = a.load();
    
  • store:將一個值存儲到原子變量中

    std::atomic<int> a(1);
    a.store(2); // a的值變為2
    
  • exchange:將原子變量的值替換為另外一個值,并返回舊值

    常用來在并發環境下進行“交換”操作。

    std::atomic<int> a(1);
    int old_value = a.exchange(2); // old_value為1,a的值變為2
    
  • compare_exchange_weak / compare_exchange_strong:原子地進行條件交換操作。若當前值等于預期值,則交換新值,否則返回falseweak失敗后可能會重新嘗試,性能相對較高;strong失敗后會返回false并不再嘗試。

    std::atomic<int> a(1);
    int expected = 1;
    if (a.compare_exchange_weak(expected, 2)) {// 如果a的值是1,設置為10std::cout << "Value changed!" << std::endl;
    } else {std::cout << "Value not changed!" << std::endl;
    }
    
  • fetch_add / fetch_sub:原子地執行加法或減法操作,并返回舊值。

    std::atomic<int> a(5);
    int old_value = a.fetch_add(1);  // old_value為5,a為6
    

7. 相關問題討論

  • 使用 std::atomic 實現線程安全計數器:C++ atomic 原子操作_c++ 原子操作-CSDN博客
  • 使用 compare_exchange_strong 實現自旋鎖:C++ atomic 原子操作_c++ 原子操作-CSDN博客
  • 原子操作支持的運算和不支持的運算:C++ atomic 原子操作_c++ 原子操作-CSDN博客
  • 什么是ABA問題,如何解決:ABA問題及其解決思路C+±CSDN博客

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/82428.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/82428.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/82428.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

雙紫擒龍紫紫紅指標源碼學習,2025升級版紫紫紅指標公式-重點技術

VAR1:MA((LOWHIGHCLOSE)/3,5); VAR2:CLOSEHHV(C,4) AND REF(C,1)LLV(C,4); 雙紫擒龍:REF(C,1)LLV(C,4) AND C>REF(C,2) OR REF(C,2)LLV(C,4) AND REF(C,1)<REF(C,3) AND REF(C,2)<REF(C,4) AND C>REF(C,1); VAR4:VAR1>REF(VAR1,1) AND REF(VAR1,1)<REF(VAR1,…

NeuralRecon技術詳解:從單目視頻中實現三維重建

引言 三維重建是計算機視覺領域中的一項關鍵技術&#xff0c;它能夠從二維圖像中恢復出三維形狀和結構。隨著深度學習的發展&#xff0c;基于學習的方法已經成為三維重建的主流。NeuralRecon是一種先進的三維重建方法&#xff0c;它能夠從單目視頻中實時生成高質量的三維模型。…

Ubuntu 上開啟 SSH 服務、禁用密碼登錄并僅允許密鑰認證

1. 安裝 OpenSSH 服務 如果尚未安裝 SSH 服務&#xff0c;運行以下命令&#xff1a; sudo apt update sudo apt install openssh-server2. 啟動 SSH 服務并設置開機自啟 sudo systemctl start ssh sudo systemctl enable ssh3. 生成 SSH 密鑰對&#xff08;本地機器&#xf…

MySQL 索引的增刪改查

MySQL 索引的增刪改查 1 建表時創建索引 [UNIQUE|FULLTEXT|SPATIAL] INDEX|KEY [別名] (字段名 [(長度)] [ASC|DESC] )主鍵直接寫&#xff1a; PRIMARY KEY (Id)例如&#xff1a; CREATE TABLE people (id int NOT NULL PRIMARY KEY AUTO_INCREMENT,last_name varchar(10)…

為什么現代CSS應該選擇OKLCH:從顏色科學到設計系統革新

在數字界面中&#xff0c;顏色不僅是美學的載體&#xff0c;更是信息傳遞的重要工具。CSS Color Level 4 標準引入了 OKLCH 顏色空間, 提供??感知均勻性??&#xff08;顏色差異與實際視覺感受一致&#xff09;&#xff0c;解決傳統HSL/HSV在調整顏色時的不自然問題。文本幫…

【java】小練習--零錢通

文章目錄 前言一、項目開發流程說明二、功能實現2.1 菜單2.2 零錢通明細2.3 零錢通收益2.4 零錢通消費2.5 零錢通退出確認2.6 零錢通金額校驗2.7 完整代碼 三、零錢通OOP版 前言 本文是我跟著B站韓順平老師的 Java 教程學習時動手實現“零錢通”項目的學習筆記&#xff0c;主要…

人工智能數學基礎實驗(四):最大似然估計的-AI 模型訓練與參數優化

一、實驗目的 理解最大似然估計&#xff08;MLE&#xff09;原理&#xff1a;掌握通過最大化數據出現概率估計模型參數的核心思想。實現 MLE 與 AI 模型結合&#xff1a;使用 MLE 手動估計樸素貝葉斯模型參數&#xff0c;并與 Scikit-learn 內置模型對比&#xff0c;深入理解參…

我的第1個爬蟲程序——豆瓣Top250爬蟲的詳細步驟指南

我的第1個爬蟲程序——豆瓣Top250爬蟲的詳細步驟指南 一、創建隔離開發環境 1. 使用虛擬環境&#xff08;推薦venv&#xff09; # 在項目目錄打開終端執行 python -m venv douban_env # 創建虛擬環境 source douban_env/bin/activate # Linux/macOS激活 douban_env\Scri…

STM32八股【11】-----Linux Bootloader (U-Boot)

參考U-Boot U-Boot是什么 嵌入式Linux系統需要一個bootloader來加載系統 U-boot就是一個通用開源的嵌入式Linux bootloader 主要實現的功能&#xff1a; 初始化硬件資源&#xff08;如內存、串口、存儲器等&#xff09;從存儲介質加載Linux內核到內存中傳遞啟動參數給內核啟…

【設計模式】責任鏈+模板+工程模式使用模板

前言 方便寫出優雅&#xff0c;解耦&#xff0c;高內聚&#xff0c;高復用的代碼。 Demo // 1. 定義驗證器接口&#xff08;責任鏈模式&#xff09; public interface Validator {Validator setNext(Validator next);boolean validate(Data data); }// 2. 創建抽象驗證器&am…

Unity3D仿星露谷物語開發49之創建云杉樹

1、目標 創建一顆既可以生長又可以砍伐的云杉樹&#xff0c;這個和之前創建橡樹類似。 2、創建云杉樹預制體 創建新物體命名為CropTreeBlueSpruce&#xff0c;并且添加Box Collider 2D和Crop組件。 在CropTreeBlueSpruce下創建子物體命名為CropSprite&#xff0c;添加3個組件…

【C#】消息隊列的使用

在C#中使用消息隊列&#xff0c;通常是指使用微軟的Message Queuing (MSMQ)技術。MSMQ提供了一種異步通信協議&#xff0c;允許應用程序通過暫時存儲要發送到目的地的消息來相互通信。 安裝MSMQ 首先&#xff0c;確保你的開發機器和部署服務器上都安裝了MSMQ。可以通過“控制…

IP-guard發布新版本4.87.2241.0

IP-guard發布新版本4.87.2241.0 新版本下載地址: https://www.tec-development.com/down/IPguard/Release/V4/IPguard4.87.2241.0.zip?s=901D45ADB22CBBFE5C612DC40AFD6BFB1551A9CD54EF418D5E86BBD256813867 新版本升級地址:

【Linux 服務器磁盤映像備份與恢復實戰指南】虛擬機備份,物理機上云都可以用這套方案!

Linux 服務器磁盤映像備份與恢復實戰指南 背景 在服務器運維中&#xff0c;磁盤健康度下降可能導致數據丟失風險&#xff0c;特別是在未配置 RAID 的情況下。針對這種情況&#xff0c;備份磁盤數據并恢復到新設備是確保數據安全的關鍵。本文記錄了使用 dd 命令通過 NFS 實現全…

深入理解 Linux 的 set、env 和 printenv 命令

在 Linux 和類 Unix 系統中&#xff0c;環境變量是配置和管理 Shell 及進程行為的核心機制。set、env 和 printenv 是與環境變量交互的三個重要命令&#xff0c;每個命令都有其獨特的功能和用途。本文將詳細探討這三個命令的區別&#xff0c;幫助大家更好地理解和使用這些命令。…

icexmoon-tree

icexmoon-tree 一個輕量級的 Java 工具庫&#xff0c;提供樹形結構操作功能。 安裝 <dependency><groupId>cn.icexmoon</groupId><artifactId>icexmoon-tree</artifactId><version>1.0.0</version> </dependency>使用 構建…

機器學習在智能水泥基復合材料中的應用與實踐

“機器學習在智能水泥基復合材料中的應用與實踐” 課程 內容 機器學習基礎模型與復合材料研究融合 機器學習在復合材料中的應用概述機器學習用于復合材料研究的流程復合材料數據收集與數據預處理 實例&#xff1a;數據的收集和預處理 復合材料機器學習特征工程與選擇 實例&a…

微軟 Build 2025:開啟 AI 智能體時代的產業革命

在 2025 年 5 月 19 日的微軟 Build 開發者大會上&#xff0c;薩提亞?納德拉以 "我們已進入 AI 智能體時代" 的宣言&#xff0c;正式拉開了人工智能發展的新紀元。這場匯聚了奧特曼、黃仁勛、馬斯克三位科技領袖的盛會&#xff0c;不僅發布了 50 余項創新產品&#…

[Java惡補day6] 15. 三數之和

給你一個整數數組 nums &#xff0c;判斷是否存在三元組 [nums[i], nums[j], nums[k]] 滿足 i ! j、i ! k 且 j ! k &#xff0c;同時還滿足 nums[i] nums[j] nums[k] 0 。請你返回所有和為 0 且不重復的三元組。 注意&#xff1a;答案中不可以包含重復的三元組。 示例 1&a…

《黃帝內經》數學建模與形式化表征方式的重構

黃帝內經的數學概括&#xff1a;《黃帝內經》數學建模與形式化表征方式的重構 摘要&#xff1a;《黃帝內經》通過現代數學理論如動力系統、代數拓撲和隨機過程&#xff0c;被重構為一個形式化的人體健康模型。該模型包括陰陽動力學的微分幾何、五行代數的李群結構、經絡拓撲與同…