为什么在线程中增加一个整数不会改变线程外的值?

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“解决”了这个问题,但这不是解决方案。此外,最终我需要从该工作函数中获得更多结果,如果我引用一个变量,它会告诉我不能多次借用,我真的不明白。

totali64 类型,它实现了 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);
  });
}