Rustの標準ライブラリには、安全にマルチスレッド処理を行うための基本的な同期プリミティブが含まれています:
AtomicBool、AtomicUsizeなど) — ロックなしでの読み書き操作をハードウェアレベルで提供します;例:
use std::sync::{Arc, Mutex}; use std::thread; fn main() { let counter = Arc::new(Mutex::new(0)); let mut handles = vec![]; for _ in 0..10 { let counter = Arc::clone(&counter); let handle = thread::spawn(move || { let mut num = counter.lock().unwrap(); *num += 1; }); handles.push(handle); } for handle in handles { handle.join().unwrap(); } println!("Result: {}", *counter.lock().unwrap()); }
質問: Rustは、Mutex<T>の使用がデッドロックを完全に排除することをコンパイル時に保証しているか?
回答: いいえ。Rustは所有権と借用チェッカーを通じてデータへの安全なアクセスを提供しますが、言語レベルでデッドロックを防ぐものではありません。デッドロックは、複数のMutexを獲得する順序が破られたり、その再帰的獲得によって論理的に発生します。例:
use std::sync::Mutex; let lock1 = Mutex::new(0); let lock2 = Mutex::new(0); // スレッド1: lock1 -> lock2, スレッド2: lock2 -> lock1 ⇒ デッドロック
ヒストリー
ヒストリー
Mutex<Option<T>>からRwLock<T>に大量にマイグレーションしましたが、書き込みロックが読み込みロックよりも長くなる可能性を考慮しませんでした。ピーク時には、書き込み待ちのキューによる処理遅延が数十秒に達しました。ヒストリー
プログラマーはスレッドのコストを削減しようとし、 Arc<Mutex<_>>を数百スレッドでプッシュしました。スケジューラの微妙な動作とMutexの再利用により、驚くべき相互待機が発生し、パフォーマンスが5倍に低下しました。