網站首頁 編程語言 正文
正文
在 Rust 中,原子性操作是指在多線程并發環境下對共享數據進行操作時,保證操作的原子性,即不會出現數據競爭等問題。Rust 提供了原子類型和原子操作來支持多線程并發編程。
Rust 的原子類型包括 AtomicBool
、AtomicIsize
、AtomicUsize
、AtomicPtr
等。這些類型的實現都使用了底層的原子操作指令,保證了它們的讀寫操作是原子的,不會被其他線程中斷。
在 Rust 中,原子操作由 std::sync::atomic
模塊提供。該模塊提供了一系列原子操作函數,包括:
-
load
:原子讀取一個原子類型的值。 -
store
:原子寫入一個原子類型的值。 -
swap
:原子交換一個原子類型的值。 -
compare_and_swap
:原子比較并交換一個原子類型的值。 -
fetch_add
、fetch_sub
、fetch_and
、fetch_or
、fetch_xor
等:原子地對一個原子類型進行加減、位運算等操作。
需要注意的是,原子操作并不是萬能的,不能完全避免所有的數據競爭問題。例如,如果多個線程都對同一個原子類型進行操作,就有可能出現ABA問題。為了避免這種問題,Rust 還提供了 std::sync::Arc
、std::sync::Mutex
、std::sync::RwLock
等同步原語,可以更好地保證線程安全。
總之,Rust 的原子類型和原子操作可以讓我們在多線程并發編程中更加安全和高效地操作共享數據。但需要注意,正確地使用原子類型和原子操作需要對并發編程有深刻的理解,并避免過度依賴原子操作來避免競態條件。
load 和 store
load
和 store
是原子類型的兩個基本操作函數。load
函數用于原子地讀取一個原子類型的值,而 store
函數用于原子地寫入一個原子類型的值。
下面是具體的代碼案例:
use std::sync::atomic::{AtomicI32, Ordering}; fn main() { // 創建一個原子整數類型,并設置初始值為 42 let counter = AtomicI32::new(42); // 原子地讀取計數器的值 let value = counter.load(Ordering::Relaxed); println!("counter value: {}", value); // 原子地將計數器的值增加 10 counter.store(value + 10, Ordering::Relaxed); // 原子地讀取計數器的新值 let new_value = counter.load(Ordering::Relaxed); println!("new counter value: {}", new_value); }
在這個例子中,我們創建了一個原子整數類型 AtomicI32
,并設置初始值為 42。接著,我們使用 load
函數原子地讀取了計數器的值,并使用 store
函數原子地將計數器的值增加 10。最后,我們又使用 load
函數原子地讀取了計數器的新值,并打印輸出。
需要注意的是,load
和 store
函數都需要指定一個 Ordering
參數。Ordering
參數用于指定原子操作的內存順序,可以控制不同線程之間的操作順序,以及對其他共享變量的影響。具體來說,Ordering
參數有以下幾種取值:
-
Relaxed
:表示對內存順序沒有任何要求。 -
Acquire
:表示讀取操作需要獲取鎖或同步,用于同步其他線程對內存的修改。 -
Release
:表示寫入操作需要釋放鎖或同步,用于同步其他線程對內存的讀取。 -
AcqRel
:表示既需要獲取鎖或同步,又需要釋放鎖或同步。 -
SeqCst
:表示需要嚴格按照順序執行所有原子操作。
一般來說,使用 Relaxed
內存順序可以獲得最好的性能,但可能會出現一些意想不到的行為。而使用 SeqCst
內存順序可以獲得最嚴格的同步語義,但也會犧牲一些性能。具體使用哪種內存順序需要根據具體情況進行權衡。
使用 AtomicBool實現通知線程停止的案例
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use std::thread; fn main() { // 創建一個原子布爾類型,并設置初始值為 false let running = Arc::new(AtomicBool::new(true)); // 創建一個新線程,用于執行耗時的操作 let running_clone = Arc::clone(&running); let handle = thread::spawn(move || { loop { // 檢查是否需要停止運行 if !running_clone.load(Ordering::Relaxed) { break; } // 執行耗時的操作 println!("working..."); // 模擬耗時操作 thread::sleep(std::time::Duration::from_secs(1)); } }); // 等待一段時間后通知線程停止運行 thread::sleep(std::time::Duration::from_secs(5)); running.store(false, Ordering::Relaxed); // 等待線程執行完畢 handle.join().unwrap(); }
在這個例子中,我們創建了一個原子布爾類型 AtomicBool
,并設置初始值為 true。接著,我們創建了一個新線程,用于執行耗時的操作。在循環中,我們首先檢查 running
變量的值,如果為 false,則退出循環,停止運行。否則,我們執行耗時的操作,并模擬一秒鐘的等待時間。
在主線程中,我們等待 5 秒鐘后,將 running
變量的值設為 false,通知線程停止運行。最后,我們等待線程執行完畢,并調用 join
方法等待線程結束。
需要注意的是,我們在設置 running
變量的值時使用了 Ordering::Relaxed
,這意味著對 running
變量的修改不需要同步到其他線程中。在這個例子中,由于只有一個線程在修改 running
變量的值,因此使用 Relaxed
訂單是安全的。如果在實際代碼中需要更強的同步保證,應該使用更高級別的 Ordering
訂單,例如 Ordering::Acquire
和 Ordering::Release
。
原文鏈接:https://juejin.cn/post/7203752514843557943
- 上一篇:沒有了
- 下一篇:沒有了
相關推薦
- 2022-06-14 Docker安裝運行SRS的過程記錄_docker
- 2022-04-05 Python?Opencv基于透視變換的圖像矯正_python
- 2022-08-01 詳解Selenium中元素定位方式_python
- 2023-01-28 GoLang?nil與interface的空指針深入分析_Golang
- 2022-08-15 詳解Redis分布式鎖的原理與實現_Redis
- 2022-10-30 Django視圖層與模板層實例詳解_python
- 2022-12-28 jquery實現點擊瀏覽器返回上一頁按鈕并能直接刷新_jquery
- 2022-11-06 Android淺析viewBinding和DataBinding_Android
- 欄目分類
-
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支