tezvyn:

Rust's `std::sync::Mutex`: Guarding Shared Data

AI-drafted, machine-checkedSource: doc.rust-lang.orgintermediate

A Rust `Mutex` guards shared data, granting access only via a temporary RAII "guard" that auto-releases the lock. It's used inside an `Arc` for safe multi-threaded mutation.

WHY IT EXISTS When multiple threads try to modify the same data simultaneously, it can lead to data races and unpredictable behavior. A Mutex (Mutual Exclusion) primitive was invented to solve this by ensuring only one thread can access a piece of data at any given time.

THE MENTAL MODEL Think of a Mutex as a room containing some data, with only one key. A thread must acquire the key to enter the room and access the data. In Rust, calling .lock() gives you a special "guard" object that holds the key. When that guard goes out of scope (e.g., at the end of a function block), the key is automatically returned, and the lock is released. This prevents you from forgetting to unlock it.

HOW IT WORKS You wrap your shared data in a Mutex<T>. To access it, a thread calls the .lock() method, which blocks until the lock is available. On success, it returns a Result containing a MutexGuard. This guard is a smart pointer that lets you access the inner data. When the MutexGuard is dropped, its Drop implementation automatically releases the lock. This RAII (Resource Acquisition Is Initialization) pattern is a core safety feature of Rust's Mutex.

WHEN TO USE IT Use Mutex when you need to share mutable state between threads. The most common pattern is Arc<Mutex<T>>. The Arc (Atomically Reference Counted) allows multiple threads to have shared ownership of the Mutex, and the Mutex ensures that only one thread at a time can mutate the data T inside.

WHEN NOT TO USE IT Don't use a Mutex for sharing data that is never changed; an Arc<T> is sufficient. For simple numeric types, the more performant std::sync::atomic types are a better choice. Avoid holding a lock for long operations or across I/O, as it creates contention. The biggest footgun is relying on its "poisoning" feature for soundness. If a thread panics while holding a lock, the mutex is poisoned to signal that the data may be corrupt. However, this is an advisory mechanism and is not guaranteed to trigger in all panic scenarios, so unsafe code cannot rely on it for memory safety.

ONE CANONICAL EXAMPLE A common use case is a shared counter across multiple threads. The counter is wrapped in Arc::new(Mutex::new(0)). Ten threads are spawned, and each clones the Arc. Inside the thread, it calls .lock().unwrap() to get a guard, increments the number via the guard (*data += 1), and then the guard goes out of scope, releasing the lock. The .unwrap() asserts that no other thread is expected to panic while holding the lock.

Read the original → doc.rust-lang.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.