How can I guarantee that a type that doesn't implement Sync can actually be safely shared between threads?
Another solution for this case is to move a mutable reference to the item into the thread, even though mutability isn't required. Since there can be only one mutable reference, the compiler knows that it's safe to be used in another thread.
use crossbeam; // 0.7.3
use std::cell::RefCell;
fn main() {
let mut val = RefCell::new(1);
let val2 = &mut val;
crossbeam::scope(|scope| {
scope.spawn(move |_| *val2.borrow());
})
.unwrap();
}
As bluss points out:
This is allowed because
RefCell<i32>
implementsSend
.
One way would be to use a wrapper with an unsafe impl Sync
:
use crossbeam; // 0.7.3
use std::cell::RefCell;
fn main() {
struct Wrap(RefCell<i32>);
unsafe impl Sync for Wrap {};
let val = Wrap(RefCell::new(1));
crossbeam::scope(|scope| {
scope.spawn(|_| *val.0.borrow());
})
.unwrap();
}
As usual with unsafe
, it is now up to you to guarantee that the inner RefCell
is indeed never accessed from multiple threads simultaneously. As far as I understand, this should be enough for it not to cause a data race.