为什么在线程中增加一个整数不会改变线程外的值?
Why does incrementing an integer in a thread not change the value outside of the thread?
我有这个代码:
fn main() {
let mut total: i64 = 0;
let pool = ThreadPool::with_name("search worker".to_owned(), num_cpus::get());
let items = getItems(); // returns a vector of sorts
let client = blocking::Client::new();
for item in items {
let t_client = client.clone(); // must clone here for some reason
let mut took: i64 = 0;
pool.execute(move || {
took = worker(t_client);
total += took;
});
}
println!("{}", total);
}
fn worker(c: blocking::Client) -> i64 {
// do some stuff and return a value
// for sake of an example, return 25
25
}
我必须在执行调用中使用 move
子句。
问题是 total
变量的值仍然为零。看起来它在那个循环中被复制了,局部变量根本没有被修改。
我确实在 took = worker(t_client);
和 total_took += took;
上收到警告,即这些变量从未被读取过。
我最终通过将该变量设为静态并使用 unsafe
“解决”了这个问题,但这不是解决方案。此外,最终我需要从该工作函数中获得更多结果,如果我引用一个变量,它会告诉我不能多次借用,我真的不明白。
total
是 i64
类型,它实现了 Copy
trait so it's implicitly copied on moves. If you want to share some mutable value T
across multiple threads you need to wrap it in an Arc<Mutex<T>>
(Arc
docs & Mutex
docs), or in this particular case, since you're using an i64
, you can use an AtomicI64
。
根据@pretzelhammer 的回答,我写了一个小片段来说明我是如何让它工作的。
let total = Arc::new(AtomicI64::new(0));
...
for ... {
let total_c = total.clone();
pool.execute(move || {
total_c.fetch_add(es_helper::run_search(t_client, parsed), Ordering::Relaxed);
});
}
我有这个代码:
fn main() {
let mut total: i64 = 0;
let pool = ThreadPool::with_name("search worker".to_owned(), num_cpus::get());
let items = getItems(); // returns a vector of sorts
let client = blocking::Client::new();
for item in items {
let t_client = client.clone(); // must clone here for some reason
let mut took: i64 = 0;
pool.execute(move || {
took = worker(t_client);
total += took;
});
}
println!("{}", total);
}
fn worker(c: blocking::Client) -> i64 {
// do some stuff and return a value
// for sake of an example, return 25
25
}
我必须在执行调用中使用 move
子句。
问题是 total
变量的值仍然为零。看起来它在那个循环中被复制了,局部变量根本没有被修改。
我确实在 took = worker(t_client);
和 total_took += took;
上收到警告,即这些变量从未被读取过。
我最终通过将该变量设为静态并使用 unsafe
“解决”了这个问题,但这不是解决方案。此外,最终我需要从该工作函数中获得更多结果,如果我引用一个变量,它会告诉我不能多次借用,我真的不明白。
total
是 i64
类型,它实现了 Copy
trait so it's implicitly copied on moves. If you want to share some mutable value T
across multiple threads you need to wrap it in an Arc<Mutex<T>>
(Arc
docs & Mutex
docs), or in this particular case, since you're using an i64
, you can use an AtomicI64
。
根据@pretzelhammer 的回答,我写了一个小片段来说明我是如何让它工作的。
let total = Arc::new(AtomicI64::new(0));
...
for ... {
let total_c = total.clone();
pool.execute(move || {
total_c.fetch_add(es_helper::run_search(t_client, parsed), Ordering::Relaxed);
});
}