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

詳解Rust編程中的共享狀態(tài)并發(fā)執(zhí)行

 更新時(shí)間:2023年11月15日 10:40:41   作者:二進(jìn)制空間安全  
雖然消息傳遞是一個(gè)很好的處理并發(fā)的方式,但并不是唯一一個(gè),另一種方式是讓多個(gè)線(xiàn)程擁有相同的共享數(shù)據(jù),本文給大家介紹Rust編程中的共享狀態(tài)并發(fā)執(zhí)行,感興趣的朋友一起看看吧

1.共享狀態(tài)并發(fā)

雖然消息傳遞是一個(gè)很好的處理并發(fā)的方式,但并不是唯一一個(gè)。另一種方式是讓多個(gè)線(xiàn)程擁有相同的共享數(shù)據(jù)。在學(xué)習(xí)Go語(yǔ)言編程過(guò)程中大家應(yīng)該聽(tīng)到過(guò)一句口號(hào):"不要通過(guò)共享內(nèi)存來(lái)通訊"。

在某種程度上,任何編程語(yǔ)言中的信道都類(lèi)似于單所有權(quán),因?yàn)橐坏⒁粋€(gè)值傳送到信道中,將無(wú)法再使用這個(gè)值。共享內(nèi)存類(lèi)似于多所有權(quán):多個(gè)線(xiàn)程可以同時(shí)訪問(wèn)相同的內(nèi)存位置。第十五章介紹了智能指針如何使得多所有權(quán)成為可能,然而這會(huì)增加額外的復(fù)雜性,因?yàn)樾枰阅撤N方式管理這些不同的所有者。Rust 的類(lèi)型系統(tǒng)和所有權(quán)規(guī)則極大的協(xié)助了正確地管理這些所有權(quán)。作為一個(gè)例子,讓我們看看互斥器,一個(gè)更為常見(jiàn)的共享內(nèi)存并發(fā)原語(yǔ)。

互斥器(mutex)是 mutual exclusion 的縮寫(xiě),也就是說(shuō),任意時(shí)刻,其只允許一個(gè)線(xiàn)程訪問(wèn)某些數(shù)據(jù)。為了訪問(wèn)互斥器中的數(shù)據(jù),線(xiàn)程首先需要通過(guò)獲取互斥器的 (lock)來(lái)表明其希望訪問(wèn)數(shù)據(jù)。鎖是一個(gè)作為互斥器一部分的數(shù)據(jù)結(jié)構(gòu),它記錄誰(shuí)有數(shù)據(jù)的排他訪問(wèn)權(quán)。因此,我們描述互斥器為通過(guò)鎖系統(tǒng) 保護(hù)(guarding)其數(shù)據(jù)。

互斥器以難以使用著稱(chēng),因?yàn)槟悴坏貌挥涀。?/p>

  • 在使用數(shù)據(jù)之前嘗試獲取鎖。
  • 處理完被互斥器所保護(hù)的數(shù)據(jù)之后,必須解鎖數(shù)據(jù),這樣其他線(xiàn)程才能夠獲取鎖。

作為一個(gè)現(xiàn)實(shí)中互斥器的例子,想象一下在某個(gè)會(huì)議的一次小組座談會(huì)中,只有一個(gè)麥克風(fēng)。如果一位成員要發(fā)言,他必須請(qǐng)求或表示希望使用麥克風(fēng)。一旦得到了麥克風(fēng),他可以暢所欲言,然后將麥克風(fēng)交給下一位希望講話(huà)的成員。如果一位成員結(jié)束發(fā)言后忘記將麥克風(fēng)交還,其他人將無(wú)法發(fā)言。如果對(duì)共享麥克風(fēng)的管理出現(xiàn)了問(wèn)題,座談會(huì)將無(wú)法如期進(jìn)行!

正確的管理互斥器異常復(fù)雜,這也是許多人之所以熱衷于信道的原因。然而,在 Rust 中,得益于類(lèi)型系統(tǒng)和所有權(quán),我們不會(huì)在鎖和解鎖上出錯(cuò)。

2.Mutex<T>的API

作為展示如何使用互斥器的例子,讓我們從在單線(xiàn)程上下文使用互斥器開(kāi)始, 看下面的代碼:

use std::sync::Mutex;
fn main() {
    let m = Mutex::new(5);
    {
        let mut num = m.lock().unwrap();
        *num = 6;
    }
    println!("m = {:?}", m);
}

像很多類(lèi)型一樣,我們使用關(guān)聯(lián)函數(shù) new 來(lái)創(chuàng)建一個(gè) Mutex<T>。使用 lock 方法獲取鎖,以訪問(wèn)互斥器中的數(shù)據(jù)。這個(gè)調(diào)用會(huì)阻塞當(dāng)前線(xiàn)程,直到我們擁有鎖為止。

如果另一個(gè)線(xiàn)程擁有鎖,并且那個(gè)線(xiàn)程 panic 了,則 lock 調(diào)用會(huì)失敗。在這種情況下,沒(méi)人能夠再獲取鎖,所以這里選擇 unwrap 并在遇到這種情況時(shí)使線(xiàn)程 panic。

一旦獲取了鎖,就可以將返回值(在這里是num)視為一個(gè)其內(nèi)部數(shù)據(jù)的可變引用了。類(lèi)型系統(tǒng)確保了我們?cè)谑褂?m 中的值之前獲取鎖。m 的類(lèi)型是 Mutex<i32> 而不是 i32,所以 必須 獲取鎖才能使用這個(gè) i32 值。我們是不會(huì)忘記這么做的,因?yàn)榉粗?lèi)型系統(tǒng)不允許訪問(wèn)內(nèi)部的 i32 值。

Mutex<T> 是一個(gè)智能指針。更準(zhǔn)確的說(shuō),lock 調(diào)用 返回 一個(gè)叫做 MutexGuard 的智能指針。這個(gè)智能指針實(shí)現(xiàn)了 Deref 來(lái)指向其內(nèi)部數(shù)據(jù);其也提供了一個(gè) Drop 實(shí)現(xiàn)當(dāng) MutexGuard 離開(kāi)作用域時(shí)自動(dòng)釋放鎖,為此,我們不會(huì)忘記釋放鎖并阻塞互斥器為其它線(xiàn)程所用的風(fēng)險(xiǎn),因?yàn)殒i的釋放是自動(dòng)發(fā)生的。

丟棄了鎖之后,可以打印出互斥器的值,并發(fā)現(xiàn)能夠?qū)⑵鋬?nèi)部的 i32 改為 6。

3.在線(xiàn)程間共享Mutex<T>

現(xiàn)在讓我們嘗試使用 Mutex<T> 在多個(gè)線(xiàn)程間共享值。我們將啟動(dòng)十個(gè)線(xiàn)程,并在各個(gè)線(xiàn)程中對(duì)同一個(gè)計(jì)數(shù)器值加一,這樣計(jì)數(shù)器將從 0 變?yōu)?10??聪旅娴拇a:

use std::sync::Mutex;
use std::thread;
fn main() {
    let counter = Mutex::new(0);
    let mut handles = vec![];
    for _ in 0..10 {
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap();
            *num += 1;
        });
        handles.push(handle);
    }
    for handle in handles {
        handle.join().unwrap();
    }
    println!("Result: {}", *counter.lock().unwrap());
}

這里創(chuàng)建了一個(gè) counter 變量來(lái)存放內(nèi)含 i32Mutex<T>, 接下來(lái)遍歷 range 創(chuàng)建了 10 個(gè)線(xiàn)程。使用了 thread::spawn 并對(duì)所有線(xiàn)程使用了相同的閉包:它們每一個(gè)都將調(diào)用 lock 方法來(lái)獲取 Mutex<T> 上的鎖,接著將互斥器中的值加一。當(dāng)一個(gè)線(xiàn)程結(jié)束執(zhí)行,num 會(huì)離開(kāi)閉包作用域并釋放鎖,這樣另一個(gè)線(xiàn)程就可以獲取它了。

在主線(xiàn)程中,我們收集了所有的 join 句柄, 調(diào)用它們的 join 方法來(lái)確保所有線(xiàn)程都會(huì)結(jié)束。這時(shí),主線(xiàn)程會(huì)獲取鎖并打印出程序的結(jié)果。

編譯上面的代碼, Rust編譯器報(bào)了一個(gè)錯(cuò)誤:

錯(cuò)誤信息表明 counter 值在上一次循環(huán)中被移動(dòng)了。所以 Rust 告訴我們不能將 counter 鎖的所有權(quán)移動(dòng)到多個(gè)線(xiàn)程中。下面來(lái)看看如何修復(fù)這個(gè)錯(cuò)誤。

4.多線(xiàn)程和多所有權(quán)

我們先嘗試將Mutex<T>封裝進(jìn)Rc<T>中并在將所有權(quán)移入線(xiàn)程之前克隆Rc<T>,看下面代碼:

use std::rc::Rc;
use std::sync::Mutex;
use std::thread;
fn main() {
    let counter = Rc::new(Mutex::new(0));
    let mut handles = vec![];
    for _ in 0..10 {
        let counter = Rc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap();
            *num += 1;
        });
        handles.push(handle);
    }
    for handle in handles {
        handle.join().unwrap();
    }
    println!("Result: {}", *counter.lock().unwrap());
}

再一次編譯代碼,納尼, 居然又報(bào)了另一個(gè)錯(cuò)誤, 成年人的崩潰誰(shuí)能懂:

Rc<Mutex<i32>>` cannot be sent between threads safely`。這個(gè)錯(cuò)誤編譯器告訴我們?cè)蚴?`the trait `Send` is not implemented for `Rc<Mutex<i32>>

Rc<T> 并不能安全的在線(xiàn)程間共享。當(dāng) Rc<T> 管理引用計(jì)數(shù)時(shí),它必須在每一個(gè) clone 調(diào)用時(shí)增加計(jì)數(shù),并在每一個(gè)克隆被丟棄時(shí)減少計(jì)數(shù)。Rc<T> 并沒(méi)有使用任何并發(fā)原語(yǔ),來(lái)確保改變計(jì)數(shù)的操作不會(huì)被其他線(xiàn)程打斷。在計(jì)數(shù)出錯(cuò)時(shí)可能會(huì)導(dǎo)致詭異的 bug,比如可能會(huì)造成內(nèi)存泄漏,或在使用結(jié)束之前就丟棄一個(gè)值。我們所需要的是一個(gè)完全類(lèi)似 Rc<T>,又以一種線(xiàn)程安全的方式改變引用計(jì)數(shù)的類(lèi)型。

5.原子引用計(jì)數(shù)Arc<T>

在Rust標(biāo)準(zhǔn)庫(kù)中, 提供了一個(gè)名為Arc<T>的類(lèi)型, 這是一個(gè)可以安全的用于并發(fā)環(huán)境的類(lèi)型, 字母 “a” 代表 原子性(atomic),所以這是一個(gè) 原子引用計(jì)數(shù)(atomically reference counted)類(lèi)型, 將代碼修改為:

use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];
    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap();
            *num += 1;
        });
        handles.push(handle);
    }
    for handle in handles {
        handle.join().unwrap();
    }
    println!("Result: {}", *counter.lock().unwrap());
}

再次編譯代碼, 執(zhí)行結(jié)果如下:

這次終于得到結(jié)果10, 程序從0數(shù)到10, 雖然過(guò)程看上去并不明顯, 但我們卻學(xué)到了很多關(guān)于Mutex<T>和線(xiàn)程安全的內(nèi)容。

到此這篇關(guān)于Rust編程中的共享狀態(tài)并發(fā)執(zhí)行的文章就介紹到這了,更多相關(guān)Rust共享狀態(tài)并發(fā)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用systemd部署r-nacos的操作方法

    使用systemd部署r-nacos的操作方法

    r-nacos是一個(gè)用rust實(shí)現(xiàn)的nacos服務(wù),我們用它平替java?nacos以降低服務(wù)占用內(nèi)存,提升服務(wù)的穩(wěn)定性,這篇文章主要介紹了使用systemd部署r-nacos,需要的朋友可以參考下
    2024-03-03
  • Rust 語(yǔ)言中的 into() 方法及代碼實(shí)例

    Rust 語(yǔ)言中的 into() 方法及代碼實(shí)例

    在 Rust 中,into() 方法通常用于將一個(gè)類(lèi)型的值轉(zhuǎn)換為另一個(gè)類(lèi)型,這通常涉及到資源的所有權(quán)轉(zhuǎn)移,本文給大家介紹Rust 語(yǔ)言中的 into() 方法及代碼實(shí)例,感謝的朋友跟隨小編一起看看吧
    2024-03-03
  • rust類(lèi)型轉(zhuǎn)換的實(shí)現(xiàn)

    rust類(lèi)型轉(zhuǎn)換的實(shí)現(xiàn)

    Rust是類(lèi)型安全的語(yǔ)言,因此在Rust中做類(lèi)型轉(zhuǎn)換不是一件簡(jiǎn)單的事,本文主要介紹了rust類(lèi)型轉(zhuǎn)換的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • Rust for循環(huán)語(yǔ)法糖背后的API場(chǎng)景分析

    Rust for循環(huán)語(yǔ)法糖背后的API場(chǎng)景分析

    for語(yǔ)句是一種能確定循環(huán)次數(shù)的循環(huán),for 語(yǔ)句用于執(zhí)行代碼塊指定的次數(shù),今天通過(guò)本文給大家介紹Rust for循環(huán)語(yǔ)法糖背后的API場(chǎng)景分析,感興趣的朋友跟隨小編一起看看吧
    2022-11-11
  • 一步到位,教你如何在Windows成功安裝Rust

    一步到位,教你如何在Windows成功安裝Rust

    一步到位:輕松學(xué)會(huì)在Windows上安裝Rust!想快速掌握Rust編程語(yǔ)言?別再為復(fù)雜教程頭疼!這份指南將手把手帶你順利完成Windows平臺(tái)上的Rust安裝全過(guò)程,從此編碼之旅更加順暢無(wú)阻,立即閱讀,開(kāi)始你的Rust編程旅程吧!
    2024-01-01
  • Rust的基礎(chǔ)數(shù)據(jù)類(lèi)型、變量系統(tǒng)、類(lèi)型轉(zhuǎn)換以及實(shí)戰(zhàn)應(yīng)用

    Rust的基礎(chǔ)數(shù)據(jù)類(lèi)型、變量系統(tǒng)、類(lèi)型轉(zhuǎn)換以及實(shí)戰(zhàn)應(yīng)用

    本文介紹了Rust的基礎(chǔ)數(shù)據(jù)類(lèi)型、變量系統(tǒng)、類(lèi)型轉(zhuǎn)換以及實(shí)戰(zhàn)應(yīng)用,涵蓋了標(biāo)量類(lèi)型、復(fù)合類(lèi)型和字符串類(lèi)型,通過(guò)變量聲明、可變性控制、作用域規(guī)則以及Shadowing機(jī)制的學(xué)習(xí),掌握Rust的變量系統(tǒng),通過(guò)實(shí)際案例,展示了Rust在實(shí)際編程中的應(yīng)用
    2026-01-01
  • rust?創(chuàng)建多線(xiàn)程web?server的詳細(xì)過(guò)程

    rust?創(chuàng)建多線(xiàn)程web?server的詳細(xì)過(guò)程

    web?server?中主要的兩個(gè)協(xié)議是?http?和?tcp,tcp?是底層協(xié)議,http?是構(gòu)建在?tcp?之上的,本篇文章重點(diǎn)給大家介紹rust?創(chuàng)建多線(xiàn)程web?server的詳細(xì)過(guò)程,感興趣的朋友跟隨小編一起看看吧
    2023-11-11
  • 從迷你todo?命令行入門(mén)Rust示例詳解

    從迷你todo?命令行入門(mén)Rust示例詳解

    這篇文章主要為大家介紹了從一個(gè)迷你todo命令行入門(mén)Rust的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • Rust?中?Deref?Coercion講解

    Rust?中?Deref?Coercion講解

    Rust 的設(shè)計(jì)理念一向是顯式比隱式好,也就是說(shuō)所有的行為盡量在代碼中表現(xiàn)出來(lái),這篇文章主要介紹了Rust?中?Deref?Coercion?介紹,需要的朋友可以參考下
    2022-10-10
  • Rust異步Web框架Axum的深入原理解析與高級(jí)用法

    Rust異步Web框架Axum的深入原理解析與高級(jí)用法

    Axum是一個(gè)功能強(qiáng)大、簡(jiǎn)單易用的異步Web框架,基于Tokio異步運(yùn)行時(shí),具有高度模塊化的架構(gòu)和類(lèi)型安全的特點(diǎn),通過(guò)本文的介紹,我們學(xué)習(xí)了Axum框架的架構(gòu)與核心組件、路由系統(tǒng)、高級(jí)功能、性能優(yōu)化方法、實(shí)戰(zhàn)項(xiàng)目的應(yīng)用以及常見(jiàn)問(wèn)題的解決方案
    2026-03-03

最新評(píng)論

莆田市| 定边县| 潜江市| 九台市| 宜州市| 大田县| 徐州市| 江阴市| 海城市| 五华县| 龙陵县| 谢通门县| 寿宁县| 辉县市| 开封县| 安图县| 垫江县| 临湘市| 延吉市| 平顺县| 玉门市| 长顺县| 叙永县| 张家界市| 宝清县| 沁水县| 西林县| 乐安县| 阳谷县| 河津市| 德钦县| 柳林县| 虞城县| 峨边| 克东县| 临沧市| 磐石市| 叶城县| 吉水县| 尼木县| 平遥县|