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

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

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

2022-07-20 10:54 作者:Databend  | 我要投稿

引言

本文介紹一下 Rust 并發(fā)安全相關(guān)的幾個概念:Send、Sync、Arc,Mutex、RwLock 等之間的聯(lián)系。這是其中的上篇,主要介紹 Send、Sync 這兩個trait。

Rust 的所有權(quán)概念

在展開介紹并發(fā)相關(guān)的幾個概念之前,有必要先了解一下 Rust 的所有權(quán)概念,Rust 對值(value)的所有權(quán)有明確的限制:

  • 一個值只能有一個 owner。

  • 可以同時存在同一個值的多個共享的非可變引用(immutable reference)。

  • 但是只能存在一個值的可變引用(mutable reference)。

比如下面這段代碼,user 在創(chuàng)建線程之后,被移動(move)到兩個不同的線程中:

由于一個值只能有一個 owner,所以編譯器報錯,報錯信息如下:

Send 和 Sync 的約束作用

于是,如果一個類型會被多個線程所使用,是需要明確說明其共享屬性的。Send 和 Sync 這兩個 trait 作用就在于此,注意到這兩個 trait 都是 std::marker,實現(xiàn)這兩個 trait 并不需要對應(yīng)實現(xiàn)什么方法,可以理解為這兩個 trait 是類型的約束,編譯器通過這些約束在編譯時對類型進行檢查。到目前為止,暫時不展開對兩個概念的理解,先來看看兩者是如何在類型檢查中起約束作用的。比如 std::thread::spawn() 的定義如下:

可以看到,對于 spawn 傳入的函數(shù)和返回的類型,都要求滿足 Send 這個約束。結(jié)合前面 Send 的定義:

  • 函數(shù)類型 F 需要滿足 Send 約束:這是因為創(chuàng)建線程之后,需要把函數(shù)類型傳入新創(chuàng)建的線程里,于是要求所有權(quán)能夠在線程之間傳遞。

  • 返回類型需要滿足 Send 約束:這是因為創(chuàng)建線程之后,返回值也需要轉(zhuǎn)移回去原先的線程。

有了對類型的約束,編譯器就會在調(diào)用 std::thread::spawn 函數(shù)時針對類型進行檢查,比如下面這段代碼:

類型 Foo 標(biāo)記自己并不實現(xiàn) Send 這個 trait,于是在編譯的時候報錯了:

如果把 impl !Send for Foo {} 這一行去掉,代碼就能編譯通過了。
以上還有一個知識點:所有類型默認(rèn)都是滿足 Send、Sync 約束的,直到顯示聲明不滿足這個約束,比如上面的 impl !Send 就是這樣一個顯示聲明。這就帶來一個疑問:能不能跟編譯器耍一些心思,明明某個類型就不滿足這個約束,睜一只眼閉一只眼看看能不能在編譯器那里蒙混過關(guān)?
答案是不能,編譯器會檢查這個類型中所有包含的成員,只有所有成員都滿足這個約束,該類型才能算滿足約束??梢栽谏厦娴幕A(chǔ)上繼續(xù)做實驗,給 Foo 結(jié)構(gòu)體新增一個 Rc 類型的成員:

由于 Rc 并不滿足 Send 約束(即顯示聲明了impl !Send,見:impl-send1),導(dǎo)致類型 Foo 并不能蒙混過關(guān)滿足 Send 約束,編譯上面代碼時報錯信息如下:

因此:一個類型要滿足某個約束,當(dāng)且僅當(dāng)該類型下的所有成員都滿足該約束才行。理解 Send 和 Sync trait

理解 Send 和 Sync trait

繼續(xù)回到 Send 和 Sync 這兩個 trait 中來,兩者在 rust 官方文檔中定義如下:

  • Send:Types that can be transferred across thread boundaries。

  • ?Sync:Types for which it is safe to share references between threads。

上面的定義翻譯過來:

  • Send 標(biāo)記表明該類型的所有權(quán)可以在線程之間傳遞。

  • Sync 標(biāo)記表明該類型的引用可以安全的在多個線程之間被共享。

我發(fā)現(xiàn)上面的這個解釋還是有點難理解了,可以換用更直白一點的方式來解釋這兩類約束:

  • Send:

    • 滿足Send約束的類型,能在多線程之間安全的排它使用(Exclusive access is thread-safe)。

    • 滿足Send約束的類型T,表示T和&mut T(mut表示能修改這個引用,甚至于刪除即drop這個數(shù)據(jù))這兩種類型的數(shù)據(jù)能在多個線程之間傳遞,說得直白些:能在多個線程之間move值以及修改引用到的值。

  • Sync:

    • 滿足 Sync 約束的類型,能在多線程之間安全的共享使用(Shared access is thread-safe)。

    • 滿足 Sync 約束的類型T,只表示該類型能在多個線程中讀共享,即:不能move,也不能修改,僅僅只能通過引用 &T 來讀取這個值。

有了上面的定義,可以知道:一個類型 T 的引用只有在滿足 Send 約束的條件下,類型 T 才能滿足 Sync 約束(a type T is Sync if and only if &T is Send)。即:T: Sync ≡ &T: Send。

對于那些基本的類型(primitive types)而言,比如 i32 類型,大多是同時滿足 Send 和 Sync 這兩個約束的,因為這些類型的共享引用(&)既能在多個多個線程中使用,同時也能在多個線程中被修改(&mut )。

了解了 Send 和 Sync 這兩類約束,就可以接著看在并發(fā)安全中的運用了,這是下一篇的內(nèi)容。

參考資料

  • Arc and Mutex in Rust | It's all about the bit2

  • Sync in std::marker - Rust3

  • Send in std::marker - Rust4

  • Send and Sync - The Rustonomicon5

  • rust - Understanding the Send trait - Stack Overflow6

  • Understanding Rust Thread Safety7

  • An unsafe tour of Rust’s Send and Sync | nyanpasu64’s blog8

  • Rust: A unique perspective9

關(guān)于 Databend

Databend 是一款開源、彈性、低成本,基于對象存儲也可以做實時分析的新式數(shù)倉。期待您的關(guān)注,一起探索云原生數(shù)倉解決方案,打造新一代開源 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ā)于公眾號:Databend


Footnotes

  1. https://doc.rust-lang.org/std/rc/struct.Rc.html#impl-Send??

  2. https://itsallaboutthebit.com/arc-mutex??

  3. https://doc.rust-lang.org/std/marker/trait.Sync.html??

  4. https://doc.rust-lang.org/std/marker/trait.Send.html??

  5. https://doc.rust-lang.org/nomicon/send-and-sync.html??

  6. https://stackoverflow.com/questions/59428096/understanding-the-send-trait??

  7. https://onesignal.com/blog/thread-safety-rust??

  8. https://nyanpasu64.github.io/blog/an-unsafe-tour-of-rust-s-send-and-sync/#example-passing-mut-t-send-between-threads??

  9. https://limpet.net/mbrubeck/2019/02/07/rust-a-unique-perspective.html??


Rust 并發(fā)安全相關(guān)的幾個概念(上)的評論 (共 條)

分享到微博請遵守國家法律
怀仁县| 宣化县| 肥乡县| 丹凤县| 威信县| 政和县| 德兴市| 台中市| 彩票| 文水县| 海门市| 巫山县| 柳江县| 连城县| 南江县| 渝北区| 竹山县| 永丰县| 田阳县| 隆回县| 威海市| 沾化县| 舒城县| 南江县| 房山区| 北川| 乐业县| 塔城市| 神农架林区| 贵州省| 宝坻区| 冕宁县| 温州市| 盐城市| 交口县| 通榆县| 芒康县| 射阳县| 宁河县| 宽甸| 明光市|