原子操作(cpp atomic)

目錄

一.原子操作

1.原子操作的概念

2.原子變量

二.原子性

1.中間狀態描述

2.單處理器單核

3.多處理器或多核的情況下

4.cache(高速緩沖器的作用)

5.在cpu cache基礎上,cpu如何讀寫數據???

6.為什么會有緩存一致性問題

7.解決策略

三.內存序

1.為什么有內存序問題???

2.內存序規定了什么

3.六種不同的內存序

4.代碼案例

四.總結


一.原子操作

多線程下確保堆共享變量的操作在執行時不會被干擾,從而避免競態條件

1.原子操作的概念

①.原子操作定義:

對基本類型或指針進行的不可中斷的操作。

②.原子性:

確保操作在多線程環境下不被中斷,保證線程安全。

③.內存序:

理解內存序的概念,確保操作的同步性和順序性。

2.原子變量

①autoinc.cc

②原子變量的操作

③原子性

④原子操作是實現和平臺相關

二.原子性

1.中間狀態描述

要么都做要么都還沒做,不會然其他核心看到執行的一個中間狀態

2.單處理器單核

①單核單線程我們只需要保證操作的指令不會被中斷即可(調用機制)

②在硬件底層有自旋鎖

③屏蔽中斷:通過關閉處理器的中斷功能,讓處理器在執行關鍵代碼段的時候,不接收外部的請求從而保證了關鍵代碼段執行的過程中不會被打斷

3.多處理器或多核的情況下

除了不被打斷還需要避免其他核心操作相關的內存空間

①以往0x86,lock指令鎖總線,避免所有內存的訪問

②現在lock指令只需要阻止其他核心堆相關內存空間的訪問即可

4.cache(高速緩沖器的作用)

為了解決cpu運算速度與內存訪問速度不匹配的問題

5.在cpu cache基礎上,cpu如何讀寫數據???

我們可以通過寫回策略來決定

①是否命中緩存?

命中直接寫并標記為臟 ,沒命中則直接往下

②定位緩存塊,該數據是否為臟數據?

是臟數據則刷主存,不是臟數據,從內存讀取,寫入緩存,并標記為臟

①是否命中緩存?

命中直接返回,沒命中直接往下

②定位緩存塊,該數據是否為臟數據?

是臟數據則刷主存,不是臟數據,從內存讀取,寫入緩存,并標記為非臟

6.為什么會有緩存一致性問題

①cpu是多核的

②基于寫回策略將會出現緩存不一致的問題



7.解決策略

①基于總線嗅探機制實現了事務串行化,通過狀態機降低總線帶寬的壓力

②事務的串行化:“鎖”? ? ? ? ?和? ? ? ? ?“lock指令”

③MESI一致性協議

三.內存序

1.為什么有內存序問題???

①編譯器優化重排

②CPU指令優化重排

2.內存序規定了什么

①規定了多個線程訪問同一內存地址時的語義

②某個線程對內存地址的更新何時能被其他線程看見

③某個線程對內存地址訪問附件可以做什么樣的優化

3.六種不同的內存序

std::memory_order_relaxed不保證順序性,性能優先。

std::memory_order_consume讀取數據的順序不被重排(但現代編譯器會優化成 acquire)。

std::memory_order_acquire保證之前的操作不被重排到后面。

std::memory_order_release保證之后的操作不被重排到前面。

std::memory_order_acq_rel結合了 acquirerelease 的特性。

std::memory_order_seq_cst保證全局順序一致性。

補充::

4.代碼案例

std::atomic<bool> x,y;
std::atomic<int> z;void write_x_then_y()
{x.store(true,std::memory_order_relaxed);  // 1y.store(true,std::memory_order_relaxed);  // 2
}void read_y_then_x()
{while(!y.load(std::memory_order_relaxed));  // 3if(x.load(std::memory_order_relaxed))  // 4++z;
}

這種情況下沒有指定內存序的位置會導致y先變成true 然后 x依舊是false while結束死循環 if語句判斷失敗 從而z不會發生++的操作

由于使用了 std::memory_order_relaxedxy 的寫操作可能會在內存中被重排,因此 read_y_then_x 線程檢查到 xfalse 的情況是可能的。最終,這會導致 z 不一定等于 1,甚至可能為 0,取決于內存重排的情況。

#include <atomic>
#include <thread>
#include <assert.h>
#include <iostream>std::atomic<bool> x,y;
std::atomic<int> z;void write_x_then_y()
{x.store(true,std::memory_order_relaxed);  // 1y.store(true,std::memory_order_release);  // 2
}void read_y_then_x()
{while(!y.load(std::memory_order_acquire));  // 3if(x.load(std::memory_order_relaxed))  // 4++z;
}

這種情況下z的結果一定為1?

因為y讀出來是true的時候 x一定也是true

使用了 memory_order_release memory_order_acquire確保了在 y 設置為 true 之后,x 的修改在 read_y_then_x 線程中變得可見。

z 最終會等于 1,因為通過這些內存序約束,線程間的同步得到了保證。

#include <assert.h>
#include <atomic>
#include <thread>
#include <iostream>std::atomic<bool> x, y;
std::atomic<int> z;void write_x() {x.store(true, std::memory_order_seq_cst); // 1
}void write_y() {y.store(true, std::memory_order_seq_cst); // 2
}
void read_x_then_y() {while (!x.load(std::memory_order_seq_cst));if (y.load(std::memory_order_seq_cst)) // 3++z;
}
void read_y_then_x() {while (!y.load(std::memory_order_seq_cst));if (x.load(std::memory_order_seq_cst)) // 4++z;
}
int main() {for (int i = 0; i < 20; i++) {x = false;y = false;z = 0;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); // 5std::cout << z.load() << std::endl;}return 0;
}

memory_order_seq_cst 下,所有的操作會嚴格按照全序進行,因此每個線程的原子操作都是同步的。

程序的輸出 z 最終將是 02,這取決于兩個 read_* 線程的執行順序。如果兩個線程都能正確讀取到 xy,則 z 會增加到 2。

四.總結

只有我們要極致提升性能的時候才有考慮原子操作進行提升性能 ,在絕大部分時候我們只需要使用互斥鎖和條件變量即可滿足服務器開發的需求

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

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

相關文章

Unet網絡的Pytorch實現和matlab實現

文章目錄 一、Unet網絡簡介1.1 輸入圖像1.2 編碼器部分&#xff08;Contracting Path&#xff09;1.3 解碼器部分&#xff08;Expanding Path&#xff09;1.4 最后一層&#xff08;輸出&#xff09;1.5 跳躍連接&#xff08;Skip Connections&#xff09; 二、Unet網絡的Pytorc…

記錄一次JVM調優過程1

如何通過jmap 診斷&#xff0c;服務運行一段時間后內存使用量飆升的問題 通過 jmap 診斷服務運行一段時間后內存使用量飆升的問題&#xff0c;需結合堆轉儲分析、對象分布統計及工具鏈配合。以下是具體操作步驟和關鍵方法&#xff1a; 一、實時監控與初步分析 獲取進程 PID 使…

接口自動化學習五:mock工具使用

Moco簡介&#xff1a; Mock是一個簡單搭建模擬服務器的框架&#xff0c;可以用來模擬http、https、socket等協議。 原理&#xff1a; Mock會根據一些配置&#xff0c;啟動一個真正的HTTP服務&#xff08;會監聽本地的某個端口&#xff09;,當發起的請求滿足某個條件時&#xf…

若依 前后端部署

后端&#xff1a;直接把代碼從gitee上拉去到本地目錄 (https://gitee.com/y_project/RuoYi-Vue ) 注意下redis連接時password改auth 后端啟動成功 前端&#xff1a;運行前首先確保安裝了node環境&#xff0c;隨后執行&#xff1a; &#xff01;&#xff01;一定要用管理員權限…

Adaptive AUTOSAR 狀態管理和轉換——ActionItemList

在AUTOSAR的狀態轉換管理(STM,State Transition Manager) 框架中,ActionItemList 是連接 狀態機狀態(State Machine State) 與 功能組狀態(Function Group States) 的核心配置元素。 以下是其關系與作用的詳細解釋: 1. 核心概念 狀態機狀態(State Machine State) 表…

一個基于ragflow的工業文檔智能解析和問答系統

工業復雜文檔解析系統 一個基于ragflow的工業文檔智能解析和問答系統,支持多種文檔格式的解析、知識庫管理和智能問答功能。 系統功能 1. 文檔管理 支持多種格式文檔上傳(PDF、Word、Excel、PPT、圖片等)文檔自動解析和分塊處理實時處理進度顯示文檔解析結果預覽批量文檔…

linux系統下如何提交git和調試

我們默認的ubuntu20.04鏡像是沒有Git提交的工具&#xff0c;我們需要配置安裝包。 安裝和更新git的命令 sudo apt update //用于更新軟件包索引sudo apt install git //用于安裝git版本控制工具 git --version //檢查git版本,確認是否安裝成功 隨便進入linux系統下的一…

輕量級爬蟲框架Feapder入門:快速搭建企業級數據管道

一、目標與前置知識 1. 目標概述 本教程的主要目標是&#xff1a; 介紹輕量級爬蟲框架 Feapder 的基本使用方式。快速搭建一個采集豆瓣電影數據的爬蟲&#xff0c;通過電影名稱查找對應的電影詳情頁并提取相關信息&#xff08;電影名稱、導演、演員、劇情簡介、評分&#xf…

spring mvc的攔截器HandlerInterceptor 接口詳解

HandlerInterceptor 接口詳解 1. 接口方法說明 方法作用執行時機返回值/注意事項preHandle請求處理前攔截在控制器方法執行前調用返回 false 中斷后續流程&#xff1b;返回 true 繼續執行postHandle控制器方法執行后攔截在控制器方法返回結果后&#xff0c;視圖渲染前調用無返…

數據可視化 —— 柱形圖應用(大全)

一、案例一&#xff1a;單柱形圖 1.導入庫 import matplotlib.pyplot as plt import pandas as pd import numpy as np 2.給窗口名稱和畫布大小 plt.figure(num單柱形圖, figsize(6, 4), facecolorw) 3.定義x、y軸的數據 # range(0-4) x np.arange(5) # 創建數組 y1 np.a…

apijson 快速上手

apijson是強大的工具&#xff0c;簡化了CRUD的操作&#xff0c;只要有數據庫表&#xff0c;就能自動生成RESTFUL接口。但初次上手也是摸索了很長時間&#xff0c;尤其是部署與使用上&#xff0c;這里嘗試以初學者角度來說下&#xff1a; 一、好處 1、對于簡單的應用&#xff…

V4L2雜談

V4L2的開發手冊 在做v4l2的開發的時候&#xff0c; 可以使用v4l2-ctl命令協助調試和軟件開發。關于linux多媒體開發可以參考鏈接&#xff1a;https://www.linuxtv.org/wiki/index.php/Main_Page關于v4l2的api接口開發可以參考&#xff1a;https://linuxtv.org/docs.php在linux…

(五)深入了解AVFoundation-播放:多音軌、字幕、倍速播放與橫豎屏切換

引言 在之前的博客中&#xff0c;我們已經實現了一個相對完整的播放器&#xff0c;具備了基本功能&#xff0c;如播放、暫停、播放進度顯示和拖拽快進等。這為我們提供了一個堅實的基礎。接下來&#xff0c;我們將進一步擴展播放器的功能&#xff0c;使其更具靈活性和實用性&a…

3ds Max 2016的版本怎么處理 按鍵輸入被主程序截斷 C#winform窗體接受不到英文輸入

3ds Max 2016的版本怎么處理 按鍵輸入被主程序截斷 C#winform窗體接受不到英文輸入 如果窗體失去焦點應該取消 全局監聽事件 解決方案&#xff1a;在窗體失去焦點時取消全局鍵盤鉤子 為了確保 WinForms 窗體失去焦點時不再攔截鍵盤事件&#xff08;避免影響 3ds Max 或其他程…

華為手機或平板與電腦實現文件共享

1.手機或平板與電腦在同一個網絡 2.打開手機或平板端&#xff0c;設置---更多連接----快分享或華為分享打開此功能-----開啟共享至電腦 3.打開電腦&#xff0c;網絡中就可看到手機端分享的用戶名稱 4. 登陸就可訪問手機 5.常見問題 5.1 電腦未發現本機 5.2 修改了訪問密碼后再…

elemenPlus中,如何去掉el-input中 文本域 textarea自帶的邊框和角標

1、去掉角標 :deep(.el-textarea__inner) {resize: none !important; // 去除右下角圖標 }2、去除邊框&#xff0c;并自定義背景色 <el-inputref"textareaRef"v-model"tempContent":style"{--el-border-color: rgba(255,255,255,0.0),--el-input-…

xv6-labs-2024 lab2

lab-2 0. 前置 課程記錄 操作系統的隔離性&#xff0c;舉例說明就是&#xff0c;當我們的shell&#xff0c;或者qq掛掉了&#xff0c;我們不希望因為他&#xff0c;去影響其他的進程&#xff0c;所以在不同的應用程序之間&#xff0c;需要有隔離性&#xff0c;并且&#xff0…

MCU控制4G模組(標準AT命令),CatM的最大速率?

根據3GPP標準&#xff0c;Cat M1的上行峰值速率大約是1 Mbps&#xff0c;下行大約是1 Mbps。但實際速率會受到多種因素影響&#xff0c;比如網絡條件、信號強度、模塊配置等。 考慮使用AT命令時的開銷。每次發送數據都需要通過AT命令&#xff0c;比如ATQISEND&#xff0c;會引…

JavaScript(JS進階)

目錄 00閉包 01函數進階 02解構賦值 03通過forEach方法遍歷數組 04深入對象 05內置構造函數 06原型 00閉包 <!-- 閉包 --><html><body><script>// 定義&#xff1a;閉包內層函數&#xff08;匿名函數&#xff09;外層函數的變量&#xff08;s&…

6.1es新特性解構賦值

解構賦值是 ES6&#xff08;ECMAScript 2015&#xff09;引入的語法&#xff0c;通過模式匹配從數組或對象中提取值并賦值給變量。&#xff1a; 功能實現 數組解構&#xff1a;按位置匹配值&#xff0c;如 let [a, b] [1, 2]。對象解構&#xff1a;按屬性名匹配值&#xff0c;…