最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

Rust 并發(fā)安全相關(guān)的幾個(gè)概念(下)

2022-07-27 15:20 作者:Databend  | 我要投稿


引言

本文介紹 Rust 并發(fā)安全相關(guān)的幾個(gè)概念:Send、Sync、Arc,Mutex、RwLock 等之間的聯(lián)系。這是其中的下篇,主要介紹 Arc,Mutex、RwLock 這幾個(gè)線程安全相關(guān)的類(lèi)型。

在上一節(jié)[1]中,講解了 Send 和 Sync 這兩個(gè)線程安全相關(guān)的 trait,在此基礎(chǔ)上展開(kāi)其它相關(guān)類(lèi)型的講解。

Rc

Rc 是 Reference Counted(引用計(jì)數(shù))的簡(jiǎn)寫(xiě),在 Rust 中,這個(gè)數(shù)據(jù)結(jié)構(gòu)用于實(shí)現(xiàn)單線程安全的對(duì)指針的引用計(jì)數(shù)。之所以這個(gè)數(shù)據(jù)結(jié)構(gòu)只是單線程安全,是因?yàn)樵诙x中顯式聲明了并不實(shí)現(xiàn) Send 和 Sync 這兩個(gè) trait:

個(gè)中原因,是因?yàn)?Rc 內(nèi)部的實(shí)現(xiàn)中,使用了非原子的引用計(jì)數(shù)(non-atomic reference counting),因此就不能滿足線程安全的條件了。如果要在多線程中使用引用計(jì)數(shù),就要使用 Arc 這個(gè)類(lèi)型:

Arc

與 Rc 不同的是,Arc 內(nèi)部使用了原子操作來(lái)實(shí)現(xiàn)其引用計(jì)數(shù),因此 Arc 是Atomically Reference Counted(原子引用計(jì)數(shù))的簡(jiǎn)寫(xiě),能被使用在多線程環(huán)境中,缺陷是原子操作的性能消耗會(huì)更大一些。雖然 Arc 能被用在多線程環(huán)境中,并不意味著 Arc<T> 天然就實(shí)現(xiàn)了 Send 和 Sync,來(lái)看看這兩部分的聲明:


從聲明可以看出:一個(gè) Arc<T> 類(lèi)型,當(dāng)且僅當(dāng)包裹(wrap)的類(lèi)型 T 滿足 Sync 和 Send 時(shí)才能被認(rèn)為是滿足 Send 和 Sync 的類(lèi)型。來(lái)做一個(gè)實(shí)驗(yàn):

在以上的代碼中,由于在第 8 行顯示聲明了 Foo 這個(gè)類(lèi)型不滿足 Sync,所以這段代碼編譯不過(guò),報(bào)錯(cuò)信息如下:

反之,如果把第 8 行去掉,代碼就能編譯通過(guò)了。于是,這就帶來(lái)一個(gè)問(wèn)題:Arc 雖然能被用在多線程環(huán)境中,但并不是所有Arc<T> 都是線程安全的,如果里面包裹的類(lèi)型 T 并不滿足多線程安全,是不是就不能使用了?解開(kāi)這個(gè)問(wèn)題的答案請(qǐng)使用 Mutex 類(lèi)型:Mutex

Mutex

與其它語(yǔ)言不同的是,Rust 中類(lèi)似 Mutex、RwLock 這樣的結(jié)構(gòu)都有一個(gè)包裹類(lèi)型,這帶來(lái)一個(gè)好處:使用這些數(shù)據(jù)類(lèi)型保護(hù)對(duì)一個(gè)數(shù)據(jù)的訪問(wèn)時(shí),是能夠明確知道保護(hù)的哪個(gè)數(shù)據(jù)的。比如在 C 語(yǔ)言中,可能只是看到一個(gè)簡(jiǎn)單的 mutex 定義:

但是在 Rust 中,定義一個(gè) Mutex 是必須知道保護(hù)什么類(lèi)型的哪個(gè)數(shù)據(jù)的:

這無(wú)疑給閱讀代碼帶來(lái)了便利?;氐骄€程安全這個(gè)話題來(lái),Mutex 只要求包裹的類(lèi)型 T 滿足 Send 就可以將它轉(zhuǎn)成滿足 Send 和 Sync 的類(lèi)型 Mutex<T>:

這意味著:即便一個(gè)類(lèi)型只滿足了 Send,不能直接用于 Arc<T> 滿足多線程安全,但是可以通過(guò)包裝成 Mutex<T> 來(lái)達(dá)到線程安全的目的。來(lái)看看上面的代碼如何使用 Mutex 來(lái)進(jìn)行改造:

上面這段代碼中,F(xiàn)oo 類(lèi)型聲明不滿足 Sync,所以不能直接聲明 Arc<Foo> 用在多線程環(huán)境中,這一點(diǎn)上面的實(shí)驗(yàn)已經(jīng)證明。但是,可以在 Foo 外面再包一層 Mutex,變成 Arc<Mutex<Foo>> 這樣就能在多線程中使用了。即:一個(gè)只需要滿足 Send 要求的類(lèi)型 T,只要經(jīng)過(guò) Mutex 的包裹變成類(lèi)型 Mutex<T>,就變成了一個(gè)線程安全的類(lèi)型。個(gè)中原因:Mutex 只要求類(lèi)型 T 滿足 Send 即可,內(nèi)部的機(jī)制會(huì)保證這個(gè)類(lèi)型在多線程環(huán)境下安全訪問(wèn)。RwLock

RwLock

講解了 Mutex,來(lái)看看 RwLock 的使用,顧名思義:RwLock 提供了讀寫(xiě)鎖的實(shí)現(xiàn)。它的 Send 和 Sync 要求如下:

對(duì)比可以看到:RwLock<T> 要滿足 Sync,要求類(lèi)型 T 同時(shí)滿足 Send 和Sync,這個(gè)條件是比 Mutex<T> 更強(qiáng)的條件。也可以這么來(lái)理解 RwLock 和 Mutex 的區(qū)別:

  • RwLock:由于要求內(nèi)部的類(lèi)型 T 必須滿足 Sync,于是在多個(gè)線程中通過(guò) RwLock<T> 同時(shí)訪問(wèn) & T 是安全的。

  • Mutex:當(dāng) Mutex 對(duì)內(nèi)部的數(shù)據(jù)進(jìn)行加鎖操作時(shí),相當(dāng)于將內(nèi)部的數(shù)據(jù)發(fā)送到了加鎖成功的線程上,而解鎖時(shí)又會(huì)將內(nèi)部數(shù)據(jù)發(fā)送到另一個(gè)線程上,于是 Mutex<T> 就僅要求 T 滿足 Send 即可。

Because of those bounds, RwLock requires its contents to be Sync, i.e. it's safe for two threads to have a &ptr to that type at the same time. Mutex only requires the data to be Send, because conceptually you can think of it like when you lock the Mutex it sends the data to your thread, and when you unlock it the data gets sent to another thread.

(見(jiàn):Mutex vs RwLock : rust[2])Interior Mutability

Interior Mutability

Mutex 和 RwLock 的作用,除了將類(lèi)型 T 包裹起來(lái),提供對(duì)該類(lèi)型數(shù)據(jù)的多線程安全訪問(wèn)之外,還有一個(gè)大的用處:Interior mutability。在 Rust 中,如果傳入類(lèi)型方法的 Self 引用不是 mut 類(lèi)型的話,是無(wú)法對(duì)該對(duì)象的成員就行修改的,比如:

這段代碼無(wú)法編譯通過(guò),因?yàn)?foo 類(lèi)型為 Foo,因此無(wú)法修改其成員,編譯器提醒說(shuō)可以通過(guò)把變量 foo 變成可變類(lèi)型來(lái)解決:

但是,如果將內(nèi)部的成員 a 使用 Mutex 重新包裝,即便 foo 仍然不是 mut 類(lèi)型,也可以進(jìn)行修改了:

這個(gè)特點(diǎn),被稱(chēng)為內(nèi)部可變性(Interior mutability),這是 Rust 中的一個(gè)設(shè)計(jì)模式,它允許你即使在有不可變引用時(shí)也可以改變數(shù)據(jù)。

總結(jié)

  • Send 和 Sync 是線程安全類(lèi)型定義時(shí)的兩類(lèi) marker trait,提供給編譯器檢查之用。

  • 除非顯式聲明不滿足這兩個(gè) trait,否則類(lèi)型都是默認(rèn)滿足這兩個(gè) trait 的。

  • 一個(gè)類(lèi)型要滿足這兩類(lèi) trait,當(dāng)且僅當(dāng)該類(lèi)型內(nèi)部的所有成員都滿足,編譯器在編譯時(shí)會(huì)進(jìn)行檢查。

  • Rc 只能提供引用計(jì)數(shù)功能,并不能在多線程環(huán)境下使用;反之,Arc 內(nèi)部使用原子變量實(shí)現(xiàn)了引用計(jì)數(shù),因此可以在多線程環(huán)境下使用。

  • 一個(gè)類(lèi)型 T 如果只滿足 Send,可以通過(guò) Mutex 包裹成 Mutex<T> 類(lèi)型來(lái)滿足多線程安全;但是 RwLock 要求比 Mutex 更嚴(yán)格。

  • 除了多線程安全之外,Mutex 和 RwLock 等類(lèi)型還提供了內(nèi)部可變性(Interior mutability)這個(gè)作用。

參考資料

  • Arc and Mutex in Rust | It's all about the bit[3]

  • Sync in std::marker - Rust[4]

  • Send in std::marker - Rust[5]

  • Send and Sync - The Rustonomicon[6]

  • rust - Understanding the Send trait - Stack Overflow[7]

  • Understanding Rust Thread Safety[8]

  • An unsafe tour of Rust’s Send and Sync | nyanpasu64’s blog[9]

  • Rust: A unique perspective[10]

  • std::rc - Rust[11]

  • Arc in std::sync - Rust[12]

  • Mutex in std::sync - Rust[13]

  • RwLock in std::sync - Rust[14]

  • multithreading - When or why should I use a Mutex over an RwLock? - Stack Overflow[15]

引用鏈接

[1]上一節(jié): https://www.codedump.info/post/20220619-weekly-19/

[2]Mutex vs RwLock :rust:https://www.reddit.com/r/rust/comments/5bx34b/mutex_vs_rwlock/

[3]Arc and Mutex in Rust | It's all about the bit:https://itsallaboutthebit.com/arc-mutex/

[4]Sync in std::marker - Rust: https://doc.rust-lang.org/std/marker/trait.Sync.html

[5]Send in std::marker - Rust:https://doc.rust-lang.org/std/marker/trait.Send.html

[6]Send and Sync - The Rustonomicon:https://doc.rust-lang.org/nomicon/send-and-sync.html

[7]rust - Understanding the Send trait - Stack Overflow:https://stackoverflow.com/questions/59428096/understanding-the-send-trait

[8]Understanding Rust Thread Safety:https://onesignal.com/blog/thread-safety-rust/

[9]An unsafe tour of Rust’s Send and Sync | nyanpasu64’s blog:https://nyanpasu64.github.io/blog/an-unsafe-tour-of-rust-s-send-and-sync/#example-passing-mut-t-send-between-threads

[10]Rust: A unique perspective:https://limpet.net/mbrubeck/2019/02/07/rust-a-unique-perspective.html

[11]std::rc - Rust:https://doc.rust-lang.org/std/rc/index.html

[12]Arc in std::sync - Rust: https://doc.rust-lang.org/std/sync/struct.Arc.html

[13]Mutex in std::sync - Rust: https://doc.rust-lang.org/std/sync/struct.Mutex.html

[14]RwLock in std::sync - Rust: https://doc.rust-lang.org/std/sync/struct.RwLock.html#impl-Send

[15]multithreading - When or why should I use a Mutex over an RwLock? - Stack Overflow:

https://stackoverflow.com/questions/50704279/when-or-why-should-i-use-a-mutex-over-an-rwlock

關(guān)于 Databend

Databend 是一款開(kāi)源、彈性、低成本,基于對(duì)象存儲(chǔ)也可以做實(shí)時(shí)分析的新式數(shù)倉(cāng)。期待您的關(guān)注,一起探索云原生數(shù)倉(cāng)解決方案,打造新一代開(kāi)源 Data Cloud。

  • Databend 文檔:https://databend.rs/

  • Twitter:https://twitter.com/Datafuse_Labs

  • Slack:https://datafusecloud.slack.com/

  • Wechat:Databend

  • GitHub :https://github.com/datafuselabs/databend


文章首發(fā)于公眾號(hào):Databend


Rust 并發(fā)安全相關(guān)的幾個(gè)概念(下)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
富平县| 定安县| 伊川县| 唐山市| 穆棱市| 丁青县| 永福县| 亚东县| 嘉鱼县| 博白县| 云阳县| 德钦县| 广西| 萝北县| 崇左市| 公安县| 南澳县| 奎屯市| 河北省| 漳州市| 视频| 云林县| 英山县| 镇巴县| 光泽县| 阿瓦提县| 仪陇县| 鲜城| 渭源县| 西盟| 南华县| 广平县| 娱乐| 科技| 安新县| 鸡东县| 卓资县| 锡林浩特市| 石屏县| 镇坪县| 大冶市|