I'd like to better understand the semantics behind the following Rust code:
use std::thread;
fn main() {
let immutable = "I am not mutable";
let mut mutable = "I am mutable";
let handle1 = thread::spawn(move || {
println!("Thread 1 says: {}", immutable);
});
let handle2 = thread::spawn(move || {
println!("Thread 2 says: {}", immutable);
});
let handle3 = thread::spawn(move || {
println!("Thread 3 says: {}", mutable);
mutable = "go away";
});
let handle4 = thread::spawn(move || {
println!("Thread 4 says: {}", mutable);
});
handle1.join().unwrap();
handle2.join().unwrap();
}
I do not understand why this code compiles. I have shared the variable mutable between multiple threads and even mutated it. What exactly is going on behind-the-scenes with the memory here? Are we making multiple pointers to the same string in static memory? Are we placing two different static strings in memory? The fact that I can have two threads reading from the same immutable item doesn't surprise me, but having two threads reading from a mutable variable does.
Note that even if thread 3 runs before 4, 4 does not reflect the updated string that thread 3 sets in its println! statement. Finally, since I didn't pass using &immutable, does this mean that the value is being "moved" into each thread rather than the actual memory address?
&static str, here the same sniped with a simple struct, play.rust-lang.org/…. - Stargateurlet mut other = mutable;. Keep in mind thatmutable: &str, notmutable: &mut str. You never change the slice itself. Or, speaking in C terms, you have achar const * mutableand achar const * const immutableand therefore are not able to change the contents anyway. And similar to C,mutable = "go away"only changes the slice, not its contents (C lingua: you change the pointer, not the pointed value), with the same semantics aslet mutable_local = mutablebeforehand, so the outermutablestays intact. - Zeta