I have code that creates a RefCell
and then wants to pass a reference to that RefCell
to a single thread:
use crossbeam; // 0.7.3
use std::cell::RefCell;
fn main() {
let val = RefCell::new(1);
crossbeam::scope(|scope| {
scope.spawn(|_| *val.borrow());
})
.unwrap();
}
In the complete code, I'm using a type that has a RefCell
embedded in it (a typed_arena::Arena
). I'm using crossbeam to ensure that the thread does not outlive the reference it takes.
This produces the error:
error[E0277]: `std::cell::RefCell<i32>` cannot be shared between threads safely
--> src/main.rs:8:15
|
8 | scope.spawn(|_| *val.borrow());
| ^^^^^ `std::cell::RefCell<i32>` cannot be shared between threads safely
|
= help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell<i32>`
= note: required because of the requirements on the impl of `std::marker::Send` for `&std::cell::RefCell<i32>`
= note: required because it appears within the type `[closure@src/main.rs:8:21: 8:38 val:&std::cell::RefCell<i32>]`
I believe I understand why this error happens: RefCell
is not designed to be called concurrently from multiple threads, and since it uses internal mutability, the normal mechanism of requiring a single mutable borrow won't prevent multiple concurrent actions. This is even documented on Sync
:
Types that are not
Sync
are those that have "interior mutability" in a non-thread-safe form, such ascell::Cell
andcell::RefCell
.
This is all well and good, but in this case, I know that only one thread is able to access the RefCell
. How can I affirm to the compiler that I understand what I am doing and I ensure this is the case? Of course, if my reasoning that this is actually safe is incorrect, I'd be more than happy to be told why.
RefCell<i32>
implementsSend
. – Achromatism