I'm trying to update the value of a.n
inside a thread. Said value is then used in the main thread for other purposes.
use std::thread;
struct foo{
n: u32
}
fn main() {
let mut a = foo{n: 0};
thread::spawn( move || {
loop {
// change the value of a according to some conditions
a.n = 1;
}
});
assert_ne!(a.n,0);
}
The issue is that, in the code above, a.n
remains 0 in the main thread.
The proximal issue that you observe comes from the closure capturing a.n
(and copying it, since it's Copy
). You can fix it by adding something like let _ = &mut a
into the closure. But it still won't compile because your code has two other issues:
You attempt to modify a value from one thread and read it from another. That's a data race, and safe Rust won't allow that to compile. The compiler enforces this by allowing only one &mut
reference to the same data to exist at once, which your code violates.
Borrow checker will complain that the borrow doesn't live long enough in the closure you're sending to thread::spawn()
. You need to either place shared data behind Arc
, or use scoped threads.
A version of your code that fixes all three issues could look like this:
use std::thread;
use std::sync::Mutex;
struct Foo {
n: Mutex<u32>,
}
fn main() {
let a = Foo { n: Mutex::new(0) };
thread::scope(|scope| {
let a = &a;
scope.spawn(move || {
loop {
*a.n.lock().unwrap() = 1;
}
});
// this assert runs in parallel with the thread, and will fail
// if it executes before the first assignment.
assert_ne!(*a.n.lock().unwrap(), 0);
});
}