Rust Mutex Basics
A Mutex is a lock on a value, like the one microphone at a meeting. Only the thread holding it may touch the value.
Wrap the value in a Mutex
Mutex::new wraps a value in a lock. The type is Mutex<i32> now, not i32:
let m = Mutex::new(5);The type will not let you skip the lock
There is no direct road to the number inside. The compiler refuses to print a Mutex as if it were a number:
let m = Mutex::new(5_i32);
println!("{m}");
// error E0277: Mutex<i32> doesn't implement std::fmt::DisplayLock it to change it
lock() waits until the lock is free, then hands you a guard. The binding stays immutable — the change happens through the guard, with * for the plain value:
let mut num = m.lock().unwrap();
*num = 6;
println!("now = {}", *num);try_lock answers at once, without waiting
Sometimes waiting is the worst option. try_lock either takes the lock immediately or reports that it is held — even when the holder is this very thread:
let m = Mutex::new(5);
let _held = m.lock().unwrap();
println!("second try got the lock = {}", m.try_lock().is_ok());A panicking holder poisons the lock
lock() returns a Result. If a holder panics while holding the lock, the lock is poisoned — and the next lock() call is an Err:
let _ = std::panic::catch_unwind(|| {
let _g = m.lock().unwrap();
panic!("the holder panics");
});
println!("next lock is Err = {}", m.lock().is_err());Example
use std::sync::Mutex;
fn main() {
let m = Mutex::new(5);
{
let mut num = m.lock().unwrap();
*num = 6;
}
println!("m = {}", *m.lock().unwrap());
}Key points
- A Mutex guards one value: the lock is the only way in, and one thread holds it at a time.
- In Rust the guard is a value — when it goes, the lock goes.
- Mutex is short for mutual exclusion.
In this example, m is a Mutex holding the number 5. Inside the block, m.lock() takes the lock and unwrap() takes the guard out of the Ok. *num = 6 changes the value through the guard. The block then ends, the guard is dropped, and the lock frees itself — no unlock line exists. The last line locks once more and prints the value through the new guard: m = 6.
Note
In many languages you lock and unlock by hand, and forgetting to unlock is a classic bug.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Rust Playground
Exercise
When is a Mutex unlocked in Rust?