Function show_notes::e022::demo_send_and_sync
source · pub fn demo_send_and_sync()
Expand description
How Send
and Sync
work
Here we have a function which spawns a thread to run println!()
. This is
silly, of course, but it works because (and only because!) String
implements the Send
trait.
pub fn demo_send() {
let foo = String::from("Hallo!");
thread::spawn(move || {
println!("{}", foo);
});
}
If we had a *non-Send
type here – e.g. an Rc<String>
instead of just a
String
– we would get a compiler error:
pub fn will_fail() {
let foo = Rc::new(String::from("Hallo!"));
thread::spawn(|| {
println!("{:?}", foo);
});
}
Instead, you’ll get a compiler error:
error[E0277]: the trait bound `std::rc::Rc<std::string::String>: std::marker::Sync` is not satisfied
--> src/e022.rs:214:5 |
214 | thread::spawn(|| {
| ^^^^^^^^^^^^^ `std::rc::Rc<std::string::String>` cannot be shared between threads safely
|
= help: the trait `std::marker::Sync` is not implemented for `std::rc::Rc<std::string::String>`
= note: required because of the requirements on the impl of `std::marker::Send` for `&std::rc::Rc<std::string::String>`
= note: required because it appears within the type `[closure@src/e022.rs:214:19: 216:6 foo:&std::rc::Rc<std::string::String>]`
= note: required by `std::thread::spawn`
Notice that it’s common to see those errors together, and notice moreover
that the error here includes both Send
and Sync
. The compiler tries to
see if foo
can be taken via reference, but the Rc
type is not Sync
,
i.e. you cannot share references to it across threads, and that’s so because
it is not Send
. (Strictly speaking, all Sync
types are Send
, but not
all Send
types must be Sync
, though off the top of my head I can’t think
of a scenario where a type would be Send
but not also Sync
.)
What’s somewhat curious is that there really isn’t a lot more than this to
demo here! To get into anything more interesting in terms of
implementation related to these traits, we’d have to be off in unsafe
land, and we haven’t talked about unsafe
at all yet, so we’re not going
to do that today. However, if you want to see a good example of what makes
for code that can be safely shared across threads, take a look at the
implementation of Vec
and the RawVec
type it’s built on! Reading the
standard library is a really good way to learn things about Rust, and it’s
surprisingly straightforward most of the time.