Rust Tutorial · Smart Pointers and Concurrency · Lesson 25 of 29
Rust Shared State: Arc and Mutex
Share data between threads safely with Arc and Mutex, and how Send and Sync prevent data races at compile time.
Arc<Mutex<T>>
Arc (atomically reference counted) shares ownership across threads; Mutex lets one thread at a time change
the data. Locking returns a guard that unlocks automatically when it goes out of scope.
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicU64, Ordering};
use std::thread;
fn main() {
let inventory = Arc::new(Mutex::new(vec![10, 10, 10]));
let requests = Arc::new(AtomicU64::new(0));
let mut handles = Vec::new();
for slot in 0..3 {
let inventory = Arc::clone(&inventory);
let requests = Arc::clone(&requests);
handles.push(thread::spawn(move || {
for _ in 0..4 {
let mut stock = inventory.lock().unwrap(); // guard unlocks at end of scope
stock[slot] -= 1;
requests.fetch_add(1, Ordering::Relaxed);
}
}));
}
for h in handles { h.join().unwrap(); }
println!("stock: {:?}, requests: {}", inventory.lock().unwrap(), requests.load(Ordering::Relaxed));
}
Output
stock: [6, 6, 6], requests: 12
Run this on your computer — see “Get Started” for setup.
Send and Sync
The compiler knows which types are safe to move (Send) or share (Sync) between threads. Trying to share an
Rc or a RefCell across threads is a compile error, so data races can't happen in safe Rust.
For many readers and few writers use RwLock; for simple counters, atomics (AtomicU64).
Test yourself
What happens if you try to share an Rc<T> between threads?
It works but is slowIt doesn't compile, because Rc isn't SendIt panics at runtimeIt causes a data race
Show answer
Answer: It doesn't compile, because Rc isn't Send