在 Rust 中,Mutex
(互斥鎖)是用于同步并發訪問共享資源的機制。Rust 標準庫中的 Mutex
結構體位于 std::sync::Mutex
中,它提供了線程安全的數據訪問。Mutex
保證了在同一時間只有一個線程可以訪問被鎖定的數據。
以下是 Mutex
的基本用法:
- 創建一個
Mutex
對象:
use std::sync::Mutex;let mutex = Mutex::new(0); // 初始化 Mutex,鎖定一個初始值為 0 的數據。
- 鎖定
Mutex
以訪問其內部數據:
let mut guard = mutex.lock().unwrap(); // 鎖定 Mutex,unwrap() 用于處理 Result 類型,簡化錯誤處理
*guard += 1; // 通過 MutexGuard 修改內部數據
// 當 MutexGuard 離開作用域時,鎖會自動釋放
- 在多線程環境中使用
Mutex
:
use std::sync::Mutex;
use std::thread;let counter = Mutex::new(0);
let mut handles = vec![];for _ in 0..10 {let counter = counter.clone(); // 克隆 Mutex 以在多個線程中使用handles.push(thread::spawn(move || {let mut num = counter.lock().unwrap();*num += 1;}));
}// 等待所有線程完成
for handle in handles {handle.join().unwrap();
}let result = counter.lock().unwrap();
println!("Result: {}", *result); // 應該輸出 10,但并發錯誤可能導致小于 10 的結果
注意:
- 使用
Mutex
時需要注意死鎖(deadlock)的情況,確保在獲取鎖之后總是適時地釋放。 Mutex::lock()
方法返回一個Result<MutexGuard<T>, PoisonError<T>>
,這是因為如果線程在持有鎖時 panic 了,Mutex
會進入“毒化”狀態。在這種情況下,其他嘗試鎖定Mutex
的線程將會收到一個PoisonError
。通常,你可以使用unwrap()
來簡化錯誤處理,但在健壯的生產代碼中,你可能需要更仔細地處理這種潛在的錯誤情況。MutexGuard
結構體實現了Deref
和DerefMut
,因此你可以直接通過它修改被鎖定的值。- 在多線程環境中,雖然
Mutex
可以保證數據訪問的線程安全性,但并不能解決所有并發問題,例如,它不能解決競態條件(race condition)問題。在上述例子中,由于線程調度的不確定性,最終結果可能小于 10。
如果你想避免由于線程調度導致的競態條件,可以考慮使用其他同步原語,如 AtomicUsize
、Barrier
、Condvar
等,或者使用消息傳遞(如使用 mpsc
通道)來避免共享狀態。