Rust 學習筆記:通過 Send 和 Sync trait 實現可擴展并發性
- Rust 學習筆記:通過 Send 和 Sync trait 實現可擴展并發性
- Send trait:允許在線程之間轉移所有權
- Sync trait:允許多線程訪問
- 手動實現 Send 和 Sync 是不安全的
- 練習題
Rust 學習筆記:通過 Send 和 Sync trait 實現可擴展并發性
處理并發的選項并不局限于語言或標準庫。
你可以編寫自己的并發特性,也可以使用其他人編寫的并發特性。
Send 和 Sync trait 是 Rust 標準庫下的 marker trait。
Send trait:允許在線程之間轉移所有權
Send trait 表明實現 Send 的類型的值的所有權可以在線程之間轉移。
幾乎每個 Rust 類型都是 Send,但也有一些例外,比如 Rc<T>。
Rc<T> 不能實現 Send,因為如果你克隆了一個 Rc<T> 值,并試圖將克隆的所有權轉移給另一個線程,兩個線程可能同時更新引用計數。出于這個原因,Rc<T> 是為在單線程情況下使用而實現的。
Rust 的類型系統和 trait 約束確保不會將非 Send 類型跨線程發送。
任何完全由 Send 類型組成的類型也會自動標記為 Send。
幾乎所有基本類型都實現了 Send,原始指針除外。
Sync trait:允許多線程訪問
Sync trait 表明,從多個線程引用實現 Sync 的類型是安全的。
換句話說,如果 &T(對 T 的不可變引用)實現了 Send,則任何類型 T 都實現了 Sync,這意味著引用可以安全地發送到另一個線程。
與 Send 類似,基本類型都實現了 Sync,完全由實現 Sync 的類型組成的類型也實現了 Sync。
智能指針小結:
- Rc<T>:沒有實現 Send,也沒有實現 Sync。
- RefCell<T>:實現 Send(如果 T 實現 Send),沒有實現 Sync。在運行時執行的借用檢查的實現不是線程安全的。
- Mutex<T>:實現了 Send 和 Sync,可以用于與多個線程共享訪問。
- MutexGuard<'a, T>:實現 Sync(如果 T 實現 Sync),沒有實現 Send。
手動實現 Send 和 Sync 是不安全的
因為完全由實現 Send 和 Sync 的其他類型組成的類型也會自動實現 Send和 Sync,所以我們不需要手動實現這些特性。
作為 marker trait,它們甚至沒有任何方法來實現。它們只是用于執行與并發相關的不變量。
手動實現這些特征涉及實現 unsafe 的 Rust 代碼。構建不由 Send 和 Sync 部分組成的新并發類型需要仔細考慮以維護安全保證。
練習題
參考視頻:
- https://www.bilibili.com/video/BV1LdovYrEVw
假設你正在設計一個數據庫連接的 API:
struct DbConnection { /* ... */ }
impl DbConnection {fn query(&self) -> DbResult {/* ... */}
}
你的數據庫不支持從同一連接進行并發查詢。DbConnection 應該實現哪些 marker trait?
答:Send。