最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

rust使用Atomic創(chuàng)建全局變量和使用操作方法

 更新時間:2024年05月05日 11:24:09   作者:1024小神  
從 Rust1.34 版本后,就正式支持原子類型,原子指的是一系列不可被 CPU 上下文交換的機器指令,這些指令組合在一起就形成了原子操作,這篇文章主要介紹了rust使用Atomic創(chuàng)建全局變量和使用,需要的朋友可以參考下

Mutex用起來簡單,但是無法并發(fā)讀,RwLock可以并發(fā)讀,但是使用場景較為受限且性能不夠,那么有沒有一種全能性選手呢? 歡迎我們的Atomic閃亮登場。

從 Rust1.34 版本后,就正式支持原子類型。原子指的是一系列不可被 CPU 上下文交換的機器指令,這些指令組合在一起就形成了原子操作。在多核 CPU 下,當某個 CPU 核心開始運行原子操作時,會先暫停其它 CPU 內核對內存的操作,以保證原子操作不會被其它 CPU 內核所干擾。

由于原子操作是通過指令提供的支持,因此它的性能相比鎖和消息傳遞會好很多。相比較于鎖而言,原子類型不需要開發(fā)者處理加鎖和釋放鎖的問題,同時支持修改,讀取等操作,還具備較高的并發(fā)性能,幾乎所有的語言都支持原子類型。

可以看出原子類型是無鎖類型,但是無鎖不代表無需等待,因為原子類型內部使用了CAS循環(huán),當大量的沖突發(fā)生時,該等待還是得等待!但是總歸比鎖要好。

CAS 全稱是 Compare and swap, 它通過一條指令讀取指定的內存地址,然后判斷其中的值是否等于給定的前置值,如果相等,則將其修改為新的值

原子類型的一個常用場景,就是作為全局變量來使用:

use std::sync::atomic::{AtomicI32, Ordering};
use std::thread::{self, JoinHandle};
static R: AtomicI32 = AtomicI32::new(0);
fn thread_add() {
    // 多個線程修改全局變量
    for i in 0..1000 {
        R.fetch_add(1, Ordering::Relaxed);
    }
}
fn main() {
    // This will POST a body of `foo=bar&baz=quux`
    let mut init_data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let mut hand_list = Vec::with_capacity(init_data.len());
    for i in init_data {
        hand_list.push(thread::spawn(thread_add));
    }
    for h in hand_list {
        h.join().unwrap();
    }
    let r_value = R.load(Ordering::Relaxed);
    println!("全局變量最后的值是: {r_value:?}");
}

并且能夠保證數(shù)據(jù)讀寫不出錯:

以上代碼啟動了數(shù)個線程,每個線程都在瘋狂對全局變量進行加 1 操作, 最后將它與線程數(shù) * 加1次數(shù)進行比較,如果發(fā)生了因為多個線程同時修改導致了臟數(shù)據(jù),那么這兩個必將不相等。好在,它沒有讓我們失望,不僅快速的完成了任務,而且保證了 100%的并發(fā)安全性。

當然以上代碼的功能其實也可以通過Mutex來實現(xiàn),但是后者的強大功能是建立在額外的性能損耗基礎上的,因此性能會遜色不少:

Atomic實現(xiàn):673ms Mutex實現(xiàn): 1136ms

可以看到Atomic實現(xiàn)會比Mutex41%,實際上在復雜場景下還能更快(甚至達到 4 倍的性能差距)!

還有一點值得注意: 和Mutex一樣,Atomic的值具有內部可變性,你無需將其聲明為mut

use std::sync::Mutex;
use std::sync::atomic::{Ordering, AtomicU64};
struct Counter {
    count: u64
}
fn main() {
    let n = Mutex::new(Counter {
        count: 0
    });
    n.lock().unwrap().count += 1;
    let n = AtomicU64::new(0);
    n.fetch_add(0, Ordering::Relaxed);
}

這里有一個奇怪的枚舉成員Ordering::Relaxed, 看上去很像是排序作用,但是我們并沒有做排序操作?。繉嶋H上它用于控制原子操作使用的內存順序。

內存順序

內存順序是指 CPU 在訪問內存時的順序,該順序可能受以下因素的影響:

代碼中的先后順序

編譯器優(yōu)化導致在編譯階段發(fā)生改變(內存重排序 reordering)
運行階段因 CPU 的緩存機制導致順序被打亂

限定內存順序的 5 個規(guī)則:

在理解了內存順序可能存在的改變后,你就可以明白為什么 Rust 提供了Ordering::Relaxed用于限定內存順序了,事實上,該枚舉有 5 個成員:

Relaxed, 這是最寬松的規(guī)則,它對編譯器和 CPU 不做任何限制,可以亂序。
Release 釋放,設定內存屏障(Memory barrier),保證它之前的操作永遠在它之前,但是它后面的操作可能被重排到它前面。
Acquire 獲取, 設定內存屏障,保證在它之后的訪問永遠在它之后,但是它之前的操作卻有可能被重排到它后面,往往和Release在不同線程中聯(lián)合使用。
AcqRel, 是 Acquire 和 Release 的結合,同時擁有它們倆提供的保證。比如你要對一個 atomic 自增 1,同時希望該操作之前和之后的讀取或寫入操作不會被重新排序。
SeqCst 順序一致性, SeqCst就像是AcqRel的加強版,它不管原子操作是屬于讀取還是寫入的操作,只要某個線程有用到SeqCst的原子操作,線程中該SeqCst操作前的數(shù)據(jù)操作絕對不會被重新排在該SeqCst操作之后,且該SeqCst操作后的數(shù)據(jù)操作也絕對不會被重新排在SeqCst操作前。
這些規(guī)則由于是系統(tǒng)提供的,因此其它語言提供的相應規(guī)則也大同小異,大家如果不明白可以看看其它語言的相關解釋。

Atomic 能替代鎖嗎

那么原子類型既然這么全能,它可以替代鎖嗎?答案是不行:

對于復雜的場景下,鎖的使用簡單粗暴,不容易有坑
std::sync::atomic包中僅提供了數(shù)值類型的原子操作:AtomicBool, AtomicIsize, AtomicUsize, AtomicI8, AtomicU16等,而鎖可以應用于各種類型
在有些情況下,必須使用鎖來配合,例如上一章節(jié)中使用Mutex配合Condvar

Atomic 的應用場景

事實上,Atomic雖然對于用戶不太常用,但是對于高性能庫的開發(fā)者、標準庫開發(fā)者都非常常用,它是并發(fā)原語的基石,除此之外,還有一些場景適用:

無鎖(lock free)數(shù)據(jù)結構
全局變量,例如全局自增 ID, 在后續(xù)章節(jié)會介紹
跨線程計數(shù)器,例如可以用于統(tǒng)計指標
以上列出的只是Atomic適用的部分場景,具體場景需要大家未來根據(jù)自己的需求進行權衡選擇。

到此這篇關于rust使用Atomic創(chuàng)建全局變量和使用的文章就介紹到這了,更多相關rust創(chuàng)建全局變量內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Rust中的Drop特性之解讀自動化資源清理的魔法

    Rust中的Drop特性之解讀自動化資源清理的魔法

    Rust通過Drop特性實現(xiàn)了自動清理機制,確保資源在對象超出作用域時自動釋放,避免了手動管理資源時可能出現(xiàn)的內存泄漏或雙重釋放問題,智能指針如Box、Rc和RefCell都依賴于Drop來管理資源,提供了靈活且安全的資源管理方案
    2025-02-02
  • rust 中的 EBNF簡介舉例

    rust 中的 EBNF簡介舉例

    這篇文章主要介紹了rust 中的 EBNF簡介舉例,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2025-05-05
  • 深入了解Rust?結構體的使用

    深入了解Rust?結構體的使用

    結構體是一種自定義的數(shù)據(jù)類型,它允許我們將多個不同的類型組合成一個整體。下面我們就來學習如何定義和使用結構體,并對比元組與結構體之間的異同,需要的可以參考一下
    2022-11-11
  • 關于使用rust調用c++靜態(tài)庫并編譯nodejs包的問題

    關于使用rust調用c++靜態(tài)庫并編譯nodejs包的問題

    這篇文章主要介紹了使用rust調用c++靜態(tài)庫并編譯nodejs包的問題,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08
  • 深入解析Rust中的智能指針

    深入解析Rust中的智能指針

    本文介紹了Rust中的智能指針,Box、Rc、Arc、RefCell、Mutex、RwLock對應的功能、場景與常用方法,并提供了組合使用方式,以及Cow、Pin的使用方式,感興趣的朋友跟隨小編一起看看吧
    2025-10-10
  • Rust時間庫Chrono最佳使用實踐

    Rust時間庫Chrono最佳使用實踐

    本文介紹了Rust中常用的日期時間處理庫chrono,對比了標準庫std::time和chrono的功能和適用場景,并詳細講解了chrono的核心數(shù)據(jù)類型、主要操作、進階功能以及最佳實踐,感興趣的朋友跟隨小編一起看看吧
    2026-01-01
  • Rust開發(fā)WebAssembly在Html和Vue中的應用小結(推薦)

    Rust開發(fā)WebAssembly在Html和Vue中的應用小結(推薦)

    這篇文章主要介紹了Rust開發(fā)WebAssembly在Html和Vue中的應用,本文將帶領大家在普通html上和vue手腳架上都來運行wasm的流程,需要的朋友可以參考下
    2022-08-08
  • 在Rust中編寫自定義Error的詳細代碼

    在Rust中編寫自定義Error的詳細代碼

    Result<T, E> 類型可以方便地用于錯誤傳導,Result<T, E>是模板類型,實例化后可以是各種類型,但 Rust 要求傳導的 Result 中的 E 是相同類型的,所以我們需要編寫自己的 Error 類型,本文給大家介紹了在Rust中編寫自定義Error的詳細代碼,需要的朋友可以參考下
    2024-01-01
  • Rust?連接?PostgreSQL?數(shù)據(jù)庫的詳細過程

    Rust?連接?PostgreSQL?數(shù)據(jù)庫的詳細過程

    這篇文章主要介紹了Rust?連接?PostgreSQL?數(shù)據(jù)庫的完整代碼,本文圖文實例代碼相結合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-01-01
  • Rust利用tauri制作個效率小工具

    Rust利用tauri制作個效率小工具

    日常使用電腦中經(jīng)常會用到一個quicke工具中的輪盤菜單工具。但quicke免費版很多功能不支持,且它的觸發(fā)邏輯用的不舒服,經(jīng)常誤觸。所以本文就來用tauri自制一個小工具,希望對大家有所幫助
    2023-02-02

最新評論

中方县| 确山县| 株洲县| 尼木县| 芦溪县| 分宜县| 阳高县| 湛江市| 闸北区| 西充县| 西畴县| 常州市| 兴文县| 元江| 盐山县| 桂阳县| 南乐县| 华阴市| 宜兰市| 清远市| 涞源县| 彩票| 盈江县| 巴中市| 锦屏县| 溆浦县| 方山县| 江安县| 集安市| 阿坝县| 柳州市| 比如县| 满洲里市| 博湖县| 大田县| 荃湾区| 勃利县| 平泉县| 平山县| 湘潭市| 苍南县|