[Day12] Read Rust Atomics and Locks — Lock Poisoning
At Topics: Chapter 1. Basics of Rust Concurrency
Until: Lifetime of the MutexGuard
Sync to My Blog: https://my-blog-chengr4.vercel.app/posts/day12-read-rust-atomics-and-locks-lock-poisoning_230531
Notes
Lock Poisoning
A Mutex in Rust gets marked as poisoned when a thread panics while holding the lock. When that happens, the Mutex will no longer be locked, but calling its lock method will result in an Err
to indicate it has been poisoned.
Why we need to mark the mutex as poisoned?
If we do not do so, it may break assumptions made by other threads (Generate inconsistent state). By marking the mutex as poisoned, we can be forced to handle inconsistent state.
How it works?
Calling lock()
on a poisoned mutex still locks the mutex but also results in an Err
. The returned Err
contains the MutexGuard
, allowing us to correct an inconsistent state if necessary.
Lifetime of the MutexGuard
- Lock and unlock the mutex in a single statement:
// it is Mutex<Vec<i32>>
// You can lock the mutex, push an item into the Vec, and unlock the mutex again, in a single statement
list.lock().unwrap().push(1);
- We should be careful of using mutex with
match
,if let
, orwhile let
. Look at the following example:
// Bad one
if let Some(item) = list.lock().unwrap().pop() {
process_item(item); // we still hold on to the lock unnecessarily
} // The temporary guard will be dropped after here
// Good one
let item = list.lock().unwrap().pop(); // guard does get dropped here
if let Some(item) = item {
process_item(item);
}
// Similar one but is ok
// A regular if statement is always a plain boolean, which cannot borrow anything
if list.lock().unwrap().pop() == Some(1) { // guard does get dropped here
do_something();
}