While Mutex is fine for most use cases, for some multi-threaded scenarios, reads happen more often than writes from multiple threads. In that case, we can use the RwLock type, which also provides shared mutability but can do so at a more granular level. RwLock stands for Reader-Writer lock. With RwLock, we can have many readers at the same but only one writer in a given scope. This is much better than a Mutex which agnostic of the kind of access a thread wants. Using RwLock
RwLock exposes two methods:
- read: Gives read access to the thread. There can be many read invocations.
- write: Gives exclusive access to thread for writing data to the wrapped type. There can be one write access from an RwLock instance to a thread.
Here's a sample program that demonstrates using the RwLock instead of Mutex:
// thread_rwlock.rs
use std::sync::RwLock;
use std::thread;
fn main() {
let m = RwLock::new(5);
let c = thread::spawn(move || {
{
*m.write().unwrap() += 1;
}
let updated = *m.read().unwrap();
updated
});
let updated = c.join().unwrap();
println!("{:?}", updated);
}
But RwLock on some systems such as Linux, suffers from the writer starvation problem. It's a situation when readers continually access the shared resource, and writer threads never get the chance to access the shared resource.