What am I using to share an object with many threads and a single author in Rust?
What is the correct approach to share a shared object between many threads when the object can sometimes be written by the same owner?
I tried to create one object object Configuration
with multiple methods to get and set configuration keys. I would like to channel this to other threads where config items can be read. There would be bonus points if they could be written and read by everyone.
I found a Reddit thread that talks about Rc
and RefCell
; will it be correct? I think this would prevent me from borrowing an object consistently multiple times and still mutating it.
source to share
Rust has a built-in concurrency primitive for just this task called RwLock
. Together with Arc
it, you can use it to implement what you want:
use std::sync::{Arc, RwLock};
use std::sync::mpsc;
use std::thread;
const N: usize = 12;
let shared_data = Arc::new(RwLock::new(Vec::new()));
let (finished_tx, finished_rx) = mpsc::channel();
for i in 0..N {
let shared_data = shared_data.clone();
let finished_tx = finished_tx.clone();
if i % 4 == 0 {
thread::spawn(move || {
let mut guard = shared_data.write().expect("Unable to lock");
guard.push(i);
finished_tx.send(()).expect("Unable to send");
});
} else {
thread::spawn(move || {
let guard = shared_data.read().expect("Unable to lock");
println!("From {}: {:?}", i, *guard);
finished_tx.send(()).expect("Unable to send");
});
}
}
// wait until everything done
for _ in 0..N {
let _ = finished_rx.recv();
}
println!("Done");
This example is very silly, but it demonstrates what RwLock
is and how to use it.
Also note that Rc
and RefCell
/ are Cell
not suitable in a multi-threaded environment because they are not synchronized properly. Rust won't even let you use them with thread::spawn()
. To exchange data between threads, you must use Arc
, and to exchange mutable data, you must additionally use one of the synchronization primitives, for example RwLock
or Mutex
.
source to share