Rust
Mutex<T>
Do mutual exclusion with Mutex<T>.
Mutex<T>
Mutex<T> (mutual exclusion) lets only one thread access the data at a time. lock() returns a guard; the lock is held while the guard lives and released automatically when the guard is dropped:
use std::sync::{Arc, Mutex};
let sayac = Arc::new(Mutex::new(0));
let mut h = Vec::new();
for _ in 0..8 {
let s = Arc::clone(&sayac);
h.push(thread::spawn(move || {
for _ in 0..100 {
*s.lock().unwrap() += 1;
}
}));
}
In Rust the data lives inside the mutex; there's no way to reach the data without taking the lock. This makes the "forgot to lock" bug impossible.
Lock duration and deadlock
Holding the guard long makes other threads wait. If two locks are taken in different orders, two threads can wait for each other forever (deadlock). Rules: keep the lock short, don't do slow work under the lock, always take multiple locks in the same order:
{
let mut veri = kilitli.lock().unwrap();
veri.push(1);
} // the guard is dropped here, the lock opens
yavas_islem(); // without holding the lock
Rust prevents data races, but a deadlock is a logic bug and the compiler doesn't catch it.
Exercise Shared counter
Share an Arc<Mutex<i32>> counter with 8 threads; let each thread increment it 100 times. After joining all threads, print the final value.
Show example solution
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let sayac = Arc::new(Mutex::new(0));
let mut h = Vec::new();
for _ in 0..8 {
let s = Arc::clone(&sayac);
h.push(thread::spawn(move || {
for _ in 0..100 {
*s.lock().unwrap() += 1;
}
}));
}
for t in h {
t.join().unwrap();
}
println!("{}", *sayac.lock().unwrap());
}
Test yourself
-
Why does <code>lock()</code> return a <code>Result</code>?
- For timeouts
- Convention
- If a thread holding the lock panicked, the mutex becomes "poisoned"
- The lock might not be obtainable
Show answer
If a thread holding the lock panicked, the mutex becomes "poisoned" — Poisoning is a warning that the data may be inconsistent due to an interrupted update.
-
Take the lock
*s.____().unwrap() += 1;
Show answer
*s.lock().unwrap() += 1;
-
Concept and meaning
- Mutex::lock()
- MutexGuard
- guard drop
- Lock released
- poisoned
- The holder panicked
- deadlock
- Mutual waiting
Next lesson: RwLock<T>