Rust并发安全基石:Mutex与RwLock深度解析在多线程编程中,如何安全、高效地共享和修改数据是一个永恒的核心难题。Rust通过其严格的所有权和借用检查机制,在编译期就为我们杜绝了大量数据竞争问题。但当多个线程确实需要访问同一份数据时,我们就必须借助强大的同步原语(Synchronizati
在多线程编程中,如何安全、高效地共享和修改数据是一个永恒的核心难题。Rust通过其严格的所有权和借用检查机制,在编译期就为我们杜绝了大量数据竞争问题。但当多个线程确实需要访问同一份数据时,我们就必须借助强大的同步原语(Synchronization Primitives)。
Mutex(互斥锁)和RwLock(读写锁)正是Rust标准库为此提供的两大并发安全基石。本文将通过详尽的原理讲解和可运行的代码实例,带你深入探索这两者的工作机制、核心区别、适用场景,并揭示其独特的“锁中毒”(Lock Poisoning)安全策略。在此之前,我们也会先回顾单线程环境下的内部可变性工具Cell与RefCell,为彻底理解并发安全打下坚实的基础。
Cell<T>RefCell<T>MutexRwLockCell<T>Cell<T> 和 RefCell<T> 都实现了内部可变性模式。
内部可变性:通过不可变引用来修改其持有的值。
对于一个对象 T,只能存在以下两种情况之一:
&T)&mut T)Cell 只能用于单线程
&mut TCopy 的类型,get 方法可通过复制的方式获取内部值Default的类型,take 方法会将当前内部值替换为 Default::default(),并返回原来的值Cell<T>,并返回内部值Cell<T> 一般用于简单类型(如数值),因为复制/移动不会太消耗资源,它无法获取内部类型的直接引用Cell<T> 而不是其它的 Cell 类型Cell<T>实操use std::cell::Cell;
fn main() {
let cell = Cell::new(5);
assert_eq!(cell.get(), 5);
assert_eq!(cell.replace(10), 5);
assert_eq!(cell.get(), 10);
let ten = cell.into_inner();
assert_eq!(ten, 10);
let cell = Cell::new(String::from("hello"));
assert_eq!(cell.take(), "hello");
assert_eq!(cell.take(), String::default());
cell.set(String::from("world"));
assert_eq!(cell.take(), "world");
}
RustJourney/cell on main [?] is 📦 0.1.0 via 🦀 1.89.0
➜ cargo run
Compiling cell v0.1.0 (/Users/qiaopengjun/Code/Rust/RustJourney/cell)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.28s
Running `target/debug/cell`
RefCell<T>Cell<T> 不同,RefCell<T> 允许直接借用它的内部值,但是会有一点运行时开销RefCell<T> 不仅持有 T 的值,还持有一个计数器,用来追踪有多少个借用
borrow():可以获取对 RefCell 内部值的不可变引用 (&T)borrow_mut():可以获取对 RefCell 内部值的可变引用 (&mut T)try_borrow()、try_borrow_mut()、into_inner()、replace()、take()...RefCell<T> 实操use std::cell::RefCell;
fn main() {
let rc = RefCell::new(5);
println!("rc = {rc:#?}");
{
let five = rc.borrow();
let five1 = rc.borrow();
assert_eq!(*five, 5);
assert_eq!(*five1, 5);
}
let mut f = rc.borrow_mut();
*f += 10;
assert_eq!(*f, 15);
println!("f = {f:#?}");
let v = rc.try_borrow();
assert!(v.is_err());
drop(f);
// RefMut 实现了 Deref Trait
*rc.borrow_mut() += 10;
println!("rc = {rc:#?}");
}
RustJourney/cell on main [?] is 📦 0.1.0 via 🦀 1.89.0
➜ cargo run
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.04s
Running `target/debug/cell`
rc = RefCell {
value: 5,
}
f = 15
rc = RefCell {
value: 25,
}
MutexMutual Exclusion
互斥锁:一种用于保护共享数据的互斥原语。
Mutex:
Mutex两种状态 (LOCKED UNLOCKED)访问数据前需要请求锁 (lock)
处理完成时需要移除锁 (unlock)
锁定 (locked)
未锁定 (unlocked)
Mutex 锁定 Lock
Mutex 解锁 unlock
这里的 unlock 是指等着 MutexGuard 走出作用域
解锁的线程与锁定的线程应该是同一个
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!