C++ WonderTrader源碼分析之自旋鎖實現

一、介紹

在WonderTrader的文件SpinMutex.hpp定義了跨平臺的自旋鎖的實現。

二、實現原理

1、類 SpinMutex:自旋鎖實現

SpinMutex 是一個輕量級的自旋鎖(Spinlock)實現,用于多線程之間保護臨界區資源。自旋鎖通過不斷嘗試獲取鎖而不讓出 CPU 控制權,在臨界區非常短的場景下比 std::mutex 更高效

類定義與成員變量
class SpinMutex
{
private:std::atomic<bool> flag = { false };

含義:

  • flag 是一個原子布爾變量,標志鎖的狀態:
    • false:鎖未被占用。
    • true:鎖已被占用。
  • 使用 std::atomic 保證該變量在線程之間的讀寫是原子的,不會產生數據競爭。
lock() 方法:嘗試加鎖(進入臨界區)
void lock()
{for (;;){if (!flag.exchange(true, std::memory_order_acquire))break;while (flag.load(std::memory_order_relaxed)){
#ifdef _MSC_VER_mm_pause();
#else__builtin_ia32_pause();
#endif}}
}

(1)、嘗試搶鎖

if (!flag.exchange(true, std::memory_order_acquire))break;

含義:

  • 嘗試將 flag 從 false 變成 true。
  • exchange 是一個原子操作,返回交換前的值。
  • 如果原值是 false,說明鎖空閑,搶鎖成功,跳出循環。
  • memory_order_acquire 的作用:
    • 表示獲取操作:確保當前線程在獲取鎖之后,看到的所有共享內存變動是“可見的”。
    • 保證鎖之后的內存操作不會重排到 exchange 之前。

(2)、鎖被占用,進入自旋等待

while (flag.load(std::memory_order_relaxed))
{
#ifdef _MSC_VER_mm_pause();
#else__builtin_ia32_pause();
#endif
}

含義:

  • 如果搶鎖失敗,說明 flag == true,就會進入這個 while,不斷檢測鎖是否釋放。
  • 自旋期間只讀取,不嘗試修改。
  • memory_order_relaxed:
    • 只要求原子性,不需要內存可見性或順序一致性。
    • 適合用于自旋中不斷讀狀態,無需同步其他內存操作。
  • _mm_pause() / __builtin_ia32_pause():
    • 都是CPU pause 指令,告訴處理器“我在忙等,不要發熱也 不要讓亂序執行干擾這個循環”。
    • 優化超線程(HT)下的性能,降低能耗和緩存一致性壓力。
    • _mm_pause() 是 Intel/微軟的,__builtin_ia32_pause() 是 GCC/Clang 提供的

這段代碼的整體思路:

1 嘗試交換(CAS):把 flag 從 false 設置為 true。
2 成功 → 搶到鎖,退出。
3 失敗 → 等著別人釋放(即 flag 變為 false)。
4 不斷讀(load)+ pause,直到別人釋放鎖,繼續嘗試搶鎖。

unlock() 方法:釋放鎖
void unlock()
{flag.store(false, std::memory_order_release);
}

含義:

  • 將 flag 設為 false,表示鎖釋放,別人可以搶鎖了。
  • memory_order_release:
    • 表示釋放操作:保證當前線程在釋放鎖前對共享內存的所有寫操作,對下一個加鎖的線程是可見的。
    • 保證寫操作不會重排序到 store 之后。
整體流程
Thread A                      Thread B
---------                    ----------
flag == falseexchange(true) → 成功       
flag = true(鎖住)          
執行臨界區                   
↓                             
store(false)(解鎖)           load(flag)falseexchange(true) → 成功進入臨界區
2、類 SpinLock:RAII 自旋鎖管理器
構造函數:
SpinLock(SpinMutex& mtx) :_mutex(mtx) { _mutex.lock(); }

接收一個 SpinMutex 引用,并立即加鎖。

析構函數:
~SpinLock() { _mutex.unlock(); }

離開作用域時自動釋放鎖,避免忘記 unlock() 導致死鎖。

拷貝構造 & 賦值刪除:
SpinLock(const SpinLock&) = delete;
SpinLock& operator=(const SpinLock&) = delete;

禁止復制和賦值,避免一個鎖對象被多次釋放,保證線程安全。

三、使用舉例

#include "SpinMutex.hpp"
#include <vector>
#include <thread>SpinMutex spin_mtx;
int counter = 0;
void worker(int id, int loops)
{for (int i = 0; i < loops; ++i){SpinLock lock(spin_mtx); // 自動加鎖++counter;               // 臨界區// 離開作用域時自動解鎖}
}
int main() {int thread_count = 4;int loops = 100000;std::vector<std::thread> threads;threads.reserve(thread_count);for (int i = 0; i < thread_count; ++i)threads.emplace_back(worker, i, loops);for (auto& t : threads)t.join();std::cout << "Final counter = " << counter << std::endl;
}

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

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

相關文章

【AI大模型】Spring AI 基于Redis實現對話持久存儲詳解

目錄 一、前言 二、Spring AI 會話記憶介紹 2.1 Spring AI 會話記憶概述 2.2 常用的會話記憶實現方式 2.2.1 集成數據庫持久存儲會話實現步驟 2.3 適用場景 三、Spring AI基于內存會話記憶存儲 3.1 本地開發環境準備 3.2 工程搭建與集成 3.2.1 添加核心依賴 3.3.2 添…

Numpy科學計算與數據分析:Numpy數據分析與圖像處理入門

Numpy實戰&#xff1a;從數據分析到圖像處理 學習目標 通過本課程&#xff0c;學員將學會運用Numpy庫進行數據分析和圖像處理。學習如何使用Numpy進行數據的高效處理&#xff0c;以及如何利用Numpy進行基本的圖像操作。 相關知識點 Numpy的數據分析和圖像處理 學習內容 1…

Vue框架總結案例

目錄 一、驗證用戶名是否已經被注冊過 二、過濾器 三、圖書管理系統 四、axios網絡請求 一、驗證用戶名是否已經被注冊過 1.案例 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><script src"j…

hyper-v虛擬機啟動失敗:Virtual Pci Express Port無法打開電源,因為發生錯誤,找不到即插即用設備

啟動錯誤 今天啟動某個hyper-v虛擬機時&#xff0c;啟動失敗了&#xff0c;大概的錯誤信息為&#xff1a;嘗試更改“ubuntu_desktop_2204”的狀態時應用程序遇到錯誤。Virtual Pci Express Port (實例 ID 0445948B-C377-4912-AEEB-58A3D45C5694): 無法開機&#xff0c;因…

CSS包含塊與百分比取值機制完全指南

引言&#xff1a;為什么需要理解包含塊&#xff1f; 在CSS布局的世界中&#xff0c;包含塊(Containing Block) 是一個基礎但至關重要的概念。它就像是一個隱形的參考框架&#xff0c;決定了元素如何定位、尺寸如何計算以及百分比值如何解析。許多CSS開發者在使用百分比單位時遇…

Numpy科學計算與數據分析:Numpy數組操作入門:合并、分割與重塑

Numpy數組操作實戰 學習目標 通過本課程的學習&#xff0c;學員將掌握Numpy中數組的基本操作&#xff0c;包括數組的合并、分割以及重塑等技巧&#xff0c;能夠靈活運用這些操作處理數據&#xff0c;為后續的科學計算和數據分析打下堅實的基礎。 相關知識點 Numpy數組操作 …

11_Mybatis 是如何進行DO類和數據庫字段的映射的?

11_Mybatis 是如何進行DO類和數據庫字段的映射的&#xff1f; 假設 VideoAbnormalContentMapper.xml 文件有如下方法&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN&quo…

2025年滲透測試面試題總結-06(題目+回答)

安全領域各種資源&#xff0c;學習文檔&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各種好玩的項目及好用的工具&#xff0c;歡迎關注。 目錄 邏輯漏洞 一、三大高危業務邏輯漏洞及修復方案 1. 訂單金額篡改&#xff08;參數操縱&#xff09; 2. 重…

SpringBoot激活指定profile的方式

題目詳細答案在 Spring Boot 中&#xff0c;可以通過多種方式激活指定的 Profile&#xff0c;以便在不同的環境中使用不同的配置。在application.properties文件中激活可以在默認的application.properties文件中通過spring.profiles.active屬性激活某個 Profile。# application…

Pytest項目_day10(接口的參數傳遞)

接口的參數傳遞 如果我們需要在一個測試用例中使用另一個測試用例中獲得的數據&#xff0c;應該怎么辦&#xff1f; 解決方案一&#xff1a;使用函數返回值 - 我們可以在另一個測試用例中使用return來返回所需的數據&#xff0c;并在其他的測試用例中調用該測試用例&#xff08…

深信服GO面試題及參考答案(上)

Go 和 Java 的特點和區別是什么? Go 和 Java 都是靜態類型、編譯型語言,但在設計理念、語法特性、并發模型等方面存在顯著差異,具體如下: 從語言設計目標來看,Go 由 Google 開發,旨在解決大型系統開發中的復雜性,強調“簡單、高效、并發”,語法簡潔,摒棄了許多傳統面向…

BGP筆記及綜合實驗

BGP基礎一、BGP產生背景 - BGP定義&#xff1a;邊界網關協議&#xff08;BGP&#xff09;是自治系統間的動態路由協議&#xff0c;屬于外部網關協議&#xff08;EGP&#xff09;。 - 自治系統&#xff08;AS&#xff09;&#xff1a;由統一管理、運行同一IGP協議的路由器組成&a…

全棧:如何判斷自己應該下載哪個版本的Tomcat

版本兼容性矩陣 https://tomcat.apache.org/whichversion.html https://tomcat.apache.org/download-11.cgi 介紹一下這些版本的不同點&#xff1a; 一、按系統選&#xff08;優先看這個&#xff09; 1.Windows 系統&#xff08;普通使用&#xff0c;非服務自啟&#xff09…

Redis的Linux安裝

可以直接命令下載 wget http://download.redis.io/releases/redis-5.0.4.tar.gz下載好之后解壓縮&#xff0c;并且重命名為redis 由于redis是c語言編寫的&#xff0c;所以我們需要先安裝gcc&#xff0c;安裝的命令如下&#xff1a;yum -y install gcc 安裝成功后輸入 : gcc -v…

14-netty基礎-手寫rpc-提供方(服務端)-06

netty系列文章&#xff1a; 01-netty基礎-socket02-netty基礎-java四種IO模型03-netty基礎-多路復用select、poll、epoll04-netty基礎-Reactor三種模型05-netty基礎-ByteBuf數據結構06-netty基礎-編碼解碼07-netty基礎-自定義編解碼器08-netty基礎-自定義序列化和反序列化09-n…

連續時間和數字之間頻率的偏差以及相位補償

接下來需要講解在連續時間域下的角頻率以及在離散化后的數字角頻率。上面可以知道模擬角頻率和數字的區別 接下來介紹相位 相位單位是弧度無頻偏&#xff1a; 對于數字來說是對連續信號采樣后的結果&#xff0c;數字的角頻率 &#xff0c;就是相位的遞增量&#xff0c;表示每個…

《Git從入門到精通:告別版本管理混亂》

堅持用 清晰易懂的圖解 代碼語言&#xff0c;讓每個知識點變得簡單&#xff01; &#x1f680;呆頭個人主頁詳情 &#x1f331; 呆頭個人Gitee代碼倉庫 &#x1f4cc; 呆頭詳細專欄系列 座右銘&#xff1a; “不患無位&#xff0c;患所以立。” 《Git從入門到精通&#xff1a…

小紅書開源多模態視覺語言模型DOTS-VLM1

項目簡介與模型基本介紹 DOTS-VLM1 是由小紅書希實驗室(Rednote HiLab)開源的多模態視覺語言模型(Vision-Language Model, VLM),旨在推動視覺與語言理解的融合研究。DOTS-VLM1 采用主流的編碼-融合-解碼架構,支持圖片與文本的聯合理解與生成,適用于圖文問答、圖片描述、…

【Git】企業級使用

&#x1f525;個人主頁&#xff1a; 中草藥 &#x1f525;專欄&#xff1a;【中間件】企業級中間件剖析 基本概念 Git 有三個核心區域&#xff0c;分別是工作區、暫存區和版本庫&#xff0c;理解這三個區域是掌握 Git 的基礎。? ? 工作區就是我們電腦里能看到的文件目錄&…

Druid學習筆記 02、快速使用Druid的SqlParser解析

文章目錄前言本章節源碼描述認識作者官方文檔快速入門demo案例引入依賴獲取到SQL的AST(抽象語法樹)使用visitor完成表、字段、表達式解析匯總總結一、簡介1.1、和Antlr生成Parser的區別1.2、Druid SQL Parser的使用場景二、各種語法支持三、性能四、Druid SQL Parser的代碼結構…