Rust guarantees thread safety at compile time. Share data with Arc<Mutex<T>>. Communicate between threads with std::sync::mpsc channels. The compiler rejects data races.
Docs: doc.rust-lang.org
| Name | Signature | Description |
|---|---|---|
| thread::spawn | fn spawn<F,T>(f: F) -> JoinHandle<T> | Spawn new OS thread |
| handle.join | fn join(self) -> thread::Result<T> | Wait for thread and return its result |
| thread::sleep | fn sleep(dur: Duration) | Sleep current thread for duration |
| thread::current | fn current() -> Thread | Return handle to current thread |
| thread::available_parallelism | fn available_parallelism() -> Result<NonZeroUsize> | Number of available CPU cores |
| Arc::new | fn new(data: T) -> Arc<T> | Create atomically-reference-counted pointer |
| arc.clone | fn clone(&self) -> Arc<T> | Increment refcount, return new Arc |
| Mutex::new | fn new(t: T) -> Mutex<T> | Create mutual exclusion wrapper |
| mutex.lock | fn lock(&self) -> LockResult<MutexGuard<'_,T>> | Acquire lock; blocks until available |
| MutexGuard | struct MutexGuard<'a, T> | Auto-unlocks when dropped (RAII) |
| RwLock | struct RwLock<T> | Reader-writer lock (multiple readers OR one writer) |
| rwlock.read | fn read(&self) -> LockResult<RwLockReadGuard<'_,T>> | Acquire shared read lock |
| rwlock.write | fn write(&self) -> LockResult<RwLockWriteGuard<'_,T>> | Acquire exclusive write lock |
| mpsc::channel | fn channel<T>() -> (Sender<T>, Receiver<T>) | Create multi-producer single-consumer channel |
| sender.send | fn send(&self, t: T) -> Result<(),SendError<T>> | Send value to channel |
| receiver.recv | fn recv(&self) -> Result<T, RecvError> | Block until value received |
| receiver.try_recv | fn try_recv(&self) -> Result<T, TryRecvError> | Non-blocking receive attempt |
| mpsc::sync_channel | fn sync_channel<T>(bound: usize) -> (SyncSender<T>, Receiver<T>) | Bounded channel |
| AtomicUsize | struct AtomicUsize | Lock-free atomic integer |
| atomic.fetch_add | fn fetch_add(&self, val: usize, order: Ordering) -> usize | Atomic addition |
| atomic.load | fn load(&self, order: Ordering) -> usize | Atomic load |
| atomic.store | fn store(&self, val: usize, order: Ordering) | Atomic store |
| Barrier | struct Barrier | Synchronize N threads at a rendezvous point |
| Condvar | struct Condvar | Condition variable for thread coordination |
Save as main.rs in a Cargo project and run with cargo run.
use std::sync::{Arc, Mutex, mpsc};
use std::thread;
use std::time::Duration;
fn main() {
// --- Shared state with Arc<Mutex<T>> ---
let counter = Arc::new(Mutex::new(0u64));
let mut handles = vec![];
for _ in 0..8 {
let counter = Arc::clone(&counter);
handles.push(thread::spawn(move || {
for _ in 0..1000 { *counter.lock().unwrap() += 1; }
}));
}
for h in handles { h.join().unwrap(); }
println!("Counter: {} (expected 8000)", *counter.lock().unwrap());
// --- mpsc Channel ---
let (tx, rx) = mpsc::channel::<String>();
let tx2 = tx.clone();
thread::spawn(move || {
for i in 0..5 { tx.send(format!("P1-{}", i)).unwrap(); thread::sleep(Duration::from_millis(5)); }
});
thread::spawn(move || {
for i in 0..5 { tx2.send(format!("P2-{}", i)).unwrap(); thread::sleep(Duration::from_millis(5)); }
});
let mut messages: Vec<String> = (0..10).map(|_| rx.recv().unwrap()).collect();
messages.sort();
println!("Messages: {:?}", messages);
// --- Atomic counter ---
use std::sync::atomic::{AtomicUsize, Ordering};
let atomic = Arc::new(AtomicUsize::new(0));
let mut hs = vec![];
for _ in 0..4 {
let a = Arc::clone(&atomic);
hs.push(thread::spawn(move || { for _ in 0..250 { a.fetch_add(1, Ordering::Relaxed); } }));
}
for h in hs { h.join().unwrap(); }
println!("Atomic: {} (expected 1000)", atomic.load(Ordering::SeqCst));
}
// cargo run