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!("结果: {}", *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倍!