Shared state
Sometimes many threads need to read and change the same value. Rust gives you two tools for this: Mutex and Arc.
Mutex
Mutex<T> guards a value so only one thread at a time can reach it. To get at the value, call lock(). You do not need let mut for the Mutex itself.
use std::sync::Mutex;let m = Mutex::new(5);*m.lock().unwrap() += 1;lock() returns a Result. It is Err if another thread panicked while holding the lock.
Lock guards
lock() gives you a guard. Use the guard like a reference to the value. The lock is released when the guard is dropped, usually at the end of its block.
{ let mut g = m.lock().unwrap(); *g += 1;} // unlocked hereYou can also call drop(g) to unlock early. Do not lock the same Mutex again on one thread while you still hold its guard. The standard library says that may hang forever or panic.
Arc
Arc<T> is like Rc<T>, but its count is safe to change from many threads. Clone the Arc to give each thread its own handle:
use std::sync::Arc;let a = Arc::new(5);let b = Arc::clone(&a);Arc::clone and Arc::strong_count work just like the Rc ones. Like Rc, an Arc only gives shared access, so you can't change the value inside.
Arc<Mutex<T>>
Put them together to share and change one value. use std::sync::{Arc, Mutex}; brings in both names with one line.
use std::sync::{Arc, Mutex};use std::thread;let c = Arc::new(Mutex::new(0));let c2 = Arc::clone(&c);let h = thread::spawn(move || { *c2.lock().unwrap() += 1;});h.join().unwrap();Arc gives many owners. Mutex makes changes one at a time.
Remember
lock()returns a guard; dropping the guard unlocks.- Use
Arc, notRc, across threads. - Clone the
Arcbefore moving it into each thread. Arc<Mutex<T>>is the usual way to share a value you change.