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

Rust如何使用線程同時(shí)運(yùn)行代碼

 更新時(shí)間:2025年02月26日 08:55:02   作者:Hello.Reader  
Rust使用1:1線程模型,通過std::thread::spawn創(chuàng)建線程,返回JoinHandle用于等待線程完成,閉包默認(rèn)借用外部變量,使用move關(guān)鍵字轉(zhuǎn)移所有權(quán),多線程共享數(shù)據(jù)時(shí)需使用并發(fā)原語,如Mutex、RwLock、Arc等,以避免競態(tài)條件

一、Rust 的線程模型

Rust 標(biāo)準(zhǔn)庫使用的是 1:1 的線程模型,即每一個(gè)語言層的線程都對應(yīng)一個(gè)操作系統(tǒng)線程。Rust 中通過標(biāo)準(zhǔn)庫提供的 std::thread 模塊來創(chuàng)建、管理線程。

當(dāng)然,也有一些第三方庫會(huì)采用不同的線程模型,或者利用異步(async)機(jī)制來實(shí)現(xiàn)并發(fā)(比如 Rust 的 async/await 機(jī)制),在面對具體需求時(shí)可以根據(jù)實(shí)際情況做選擇。

二、創(chuàng)建線程:thread::spawn

要在 Rust 中創(chuàng)建一個(gè)新線程,可以使用 thread::spawn 函數(shù),并向它傳遞一個(gè)閉包(closure)。閉包中包含需要在線程中執(zhí)行的代碼。

例如:

use std::thread;
use std::time::Duration;

fn main() {
    // 使用 thread::spawn 創(chuàng)建新的線程
    thread::spawn(|| {
        for i in 1..10 {
            println!("hi number {} from the spawned thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

    // 主線程也執(zhí)行一些操作
    for i in 1..5 {
        println!("hi number {} from the main thread!", i);
        thread::sleep(Duration::from_millis(1));
    }
}

在上面的例子里,我們在子線程中打印數(shù)字,同時(shí)在主線程中也打印數(shù)字。由于操作系統(tǒng)會(huì)對線程進(jìn)行調(diào)度,輸出的順序無法完全預(yù)測??赡苤骶€程先打印,也可能子線程先打印,或者兩者交錯(cuò)執(zhí)行。

需要注意的是,當(dāng)主線程結(jié)束時(shí),所有通過 spawn 創(chuàng)建的子線程會(huì)被強(qiáng)制終止,即使子線程還沒有執(zhí)行完。

三、等待線程完成:JoinHandle 與 join

如果希望確保子線程的代碼一定會(huì)執(zhí)行完,那么就需要在主線程結(jié)束前等待子線程。thread::spawn 的返回值是一個(gè) JoinHandle,可以用它來調(diào)用 join 方法,阻塞(block)當(dāng)前線程,直到對應(yīng)的子線程執(zhí)行完成。

use std::thread;
use std::time::Duration;

fn main() {
    let handle = thread::spawn(|| {
        for i in 1..10 {
            println!("hi number {} from the spawned thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

    // 如果先做主線程自己的工作,再等待子線程
    for i in 1..5 {
        println!("hi number {} from the main thread!", i);
        thread::sleep(Duration::from_millis(1));
    }

    // 調(diào)用 join,阻塞主線程,直到子線程結(jié)束
    handle.join().unwrap();
}

當(dāng)我們在主線程中調(diào)用 handle.join() 時(shí),主線程會(huì)暫停執(zhí)行,直到子線程完成工作。這樣就能確保在程序退出前,所有線程都能順利完成執(zhí)行。

如果把 join 放在主線程的循環(huán)之前,那么主線程會(huì)先等待子線程結(jié)束,才會(huì)進(jìn)行自身的打印操作——這樣就不會(huì)再看到主線程與子線程的輸出交錯(cuò)了。

四、move 閉包與線程

多線程編程中常常需要在線程間傳遞數(shù)據(jù)或訪問主線程中的變量。

在 Rust 中,如果一個(gè)閉包想要捕獲外部變量,就要考慮該變量的所有權(quán)或引用生命周期問題。

4.1.問題場景

如下示例所示,如果我們在主線程中創(chuàng)建一個(gè)向量 v,然后在子線程中直接打印這個(gè)向量,就會(huì)出錯(cuò):

use std::thread;

fn main() {
    let v = vec![1, 2, 3];

    let handle = thread::spawn(|| {
        println!("Here's a vector: {:?}", v);
    });

    // ...
    handle.join().unwrap();
}

編譯時(shí),Rust 會(huì)提示閉包捕獲的是對 v 的引用,但無法保證在子線程運(yùn)行時(shí) v 依舊有效:主線程可能在子線程使用 v 之前就結(jié)束了,讓 v 不再有效,從而導(dǎo)致潛在的懸垂引用(dangling reference)。

4.2.使用 move 關(guān)鍵字

為了解決這個(gè)問題,需要在閉包前面加上 move 關(guān)鍵字,這樣可以把閉包中用到的外部數(shù)據(jù)移動(dòng)到閉包的所有權(quán)中。

use std::thread;

fn main() {
    let v = vec![1, 2, 3];

    let handle = thread::spawn(move || {
        println!("Here's a vector: {:?}", v);
    });

    handle.join().unwrap();
}

在這里,move 會(huì)把 v 的所有權(quán)從主線程轉(zhuǎn)移到子線程,從而保證子線程在使用 v 時(shí)不會(huì)遇到生命周期問題。不過需要注意的是,這樣一來,主線程就不能再使用 v 了,因?yàn)樗袡?quán)已經(jīng)被移動(dòng)出去了。

4.3.不能與 drop 共用所有權(quán)

如果嘗試同時(shí)在主線程中顯式調(diào)用 drop(v) 并且在子線程中使用 v,無論有沒有用 move,都行不通。Rust 的所有權(quán)規(guī)則會(huì)保證同一份數(shù)據(jù)不會(huì)被多次釋放或引用到失效的數(shù)據(jù)。所以,在設(shè)計(jì)多線程邏輯時(shí),需要明確劃分?jǐn)?shù)據(jù)的所有權(quán)與生命周期,以避免死鎖、競態(tài)條件或懸垂引用等問題。

五、小結(jié)

  1. Rust 標(biāo)準(zhǔn)庫中的線程模型:Rust 使用一對一(1:1)模型,每個(gè)語言線程對應(yīng)一個(gè)系統(tǒng)線程。
  2. 創(chuàng)建線程:使用 thread::spawn 來創(chuàng)建子線程,傳入一個(gè)閉包作為要執(zhí)行的代碼。
  3. 線程同步:通過返回的 JoinHandle 調(diào)用 join,可以阻塞主線程并等待子線程完成執(zhí)行。
  4. 所有權(quán)與生命周期:使用 move 關(guān)鍵字將閉包所需的變量從主線程移動(dòng)到子線程,從而避免引用沖突或無效引用。
  5. 小心共享數(shù)據(jù):當(dāng)多個(gè)線程需要同時(shí)訪問或修改同一份數(shù)據(jù)時(shí),需要使用安全的并發(fā)原語(例如 Mutex、RwLockArc 等),否則會(huì)出現(xiàn)競態(tài)條件。

在 Rust 中編寫并發(fā)程序時(shí),我們需要充分利用所有權(quán)與借用檢查器提供的安全保障,同時(shí)對多線程邏輯進(jìn)行精心設(shè)計(jì)。盡管多線程編程能帶來性能上的提升,但也應(yīng)關(guān)注潛在的風(fēng)險(xiǎn),并通過 Rust 的工具鏈和語言特性來盡量減少錯(cuò)誤,寫出更安全、更可靠的并發(fā)應(yīng)用。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • rust中trait的使用方法詳解

    rust中trait的使用方法詳解

    trait用中文來講就是特征,它就是一個(gè)標(biāo)記,只不過這個(gè)標(biāo)記被用在特定的地方,也就是類型參數(shù)的后面,下面我們就來學(xué)習(xí)一下trait的具體使用方法吧
    2023-12-12
  • 詳解Rust中三種循環(huán)(loop,while,for)的使用

    詳解Rust中三種循環(huán)(loop,while,for)的使用

    我們常常需要重復(fù)執(zhí)行同一段代碼,針對這種場景,Rust?提供了多種循環(huán)(loop)工具。一個(gè)循環(huán)會(huì)執(zhí)行循環(huán)體中的代碼直到結(jié)尾,并緊接著回到開頭繼續(xù)執(zhí)行。而?Rust?提供了?3?種循環(huán):loop、while?和?for,下面逐一講解
    2022-09-09
  • Rust anyhow 簡明示例教程

    Rust anyhow 簡明示例教程

    anyhow 是 Rust 中的一個(gè)庫,旨在提供靈活的、具體的錯(cuò)誤處理能力,建立在 std::error::Error 基礎(chǔ)上,主要用于那些需要簡單錯(cuò)誤處理的應(yīng)用程序和原型開發(fā)中,本文給大家分享Rust anyhow 簡明教程,一起看看吧
    2024-06-06
  • 利用Rust編寫一個(gè)簡單的字符串時(shí)鐘

    利用Rust編寫一個(gè)簡單的字符串時(shí)鐘

    這篇文章主要為大家詳細(xì)介紹了一個(gè)用rust寫的一個(gè)簡單的練手的demo,一個(gè)字符串時(shí)鐘,在終端用字符串方式顯示當(dāng)前時(shí)間,感興趣的小伙伴可以了解一下
    2022-12-12
  • Rust多線程Web服務(wù)器搭建過程

    Rust多線程Web服務(wù)器搭建過程

    這篇文章主要介紹了Rust多線程 Web 服務(wù)器搭建過程,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-04-04
  • Rust使用libloader調(diào)用動(dòng)態(tài)鏈接庫

    Rust使用libloader調(diào)用動(dòng)態(tài)鏈接庫

    這篇文章主要為大家介紹了Rust使用libloader調(diào)用動(dòng)態(tài)鏈接庫示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • C++的替代:微軟如何使用rust?

    C++的替代:微軟如何使用rust?

    這篇文章主要介紹了微軟如何使用rust的,幫助大家了解c++和rust這兩門編程語言的聯(lián)系與區(qū)別,感興趣的朋友可以了解下
    2020-09-09
  • rust異步編程詳細(xì)講解

    rust異步編程詳細(xì)講解

    這篇文章主要介紹了rust異步編程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-12-12
  • Rust動(dòng)態(tài)調(diào)用字符串定義的Rhai函數(shù)方式

    Rust動(dòng)態(tài)調(diào)用字符串定義的Rhai函數(shù)方式

    Rust中使用Rhai動(dòng)態(tài)調(diào)用字符串定義的函數(shù),通過eval_expression_with_scope實(shí)現(xiàn),但參數(shù)傳遞和函數(shù)名處理有局限性,使用FnCall功能更健壯,但更復(fù)雜,總結(jié)提供了更通用的方法,但需要處理更多錯(cuò)誤情況
    2025-02-02
  • rust?zip異步壓縮與解壓的代碼詳解

    rust?zip異步壓縮與解壓的代碼詳解

    在使用actix-web框架的時(shí)候,如果使用zip解壓任務(wù)將會(huì)占用一個(gè)工作線程,因?yàn)閦ip庫是同步阻塞的,想用異步非阻塞需要用另一個(gè)庫,下面介紹下rust?zip異步壓縮與解壓的示例,感興趣的朋友一起看看吧
    2024-04-04

最新評論

治多县| 北京市| 克什克腾旗| 巴东县| 尚义县| 凭祥市| 南江县| 新龙县| 广德县| 汪清县| 太仆寺旗| 自治县| 理塘县| 龙海市| 黑龙江省| 栾城县| 长兴县| 万全县| 澄城县| 聂荣县| 厦门市| 平遥县| 阿勒泰市| 吴旗县| 临桂县| 阜新市| 鹿邑县| 汉川市| 喀喇沁旗| 丹凤县| 云和县| 米林县| 焦作市| 泾阳县| 新平| 磐安县| 化州市| 黔南| 五大连池市| 兰坪| 尚义县|