无法将数据移出互斥锁

Jac*_*ark 4 multithreading asynchronous rust

考虑下面的代码示例,我有一个向量,JoinHandlers其中我需要它迭代以连接回主线程,但是,这样做我得到错误error: cannot move out of borrowed content.

let threads = Arc::new(Mutex::new(Vec::new()));

for _x in 0..100 {
     let handle = thread::spawn(move || {
          //do some work
     }

     threads.lock().unwrap().push((handle));
}

for t in threads.lock().unwrap().iter() {
     t.join();
}
Run Code Online (Sandbox Code Playgroud)

Vla*_*eev 6

不幸的是,你不能直接这样做.当使用Mutex您提供给它的数据结构时,您无法再按值返回.你只能得到&mut它的引用,这将不允许它移出它.所以即使into_iter()不起作用 - 它需要self它无法得到的论据MutexGuard.

但是,有一种解决方法.您可以使用Arc<Mutex<Option<Vec<_>>>>而不是Arc<Mutex<Vec<_>>>仅使用take()互斥锁中的值:

for t in threads.lock().unwrap().take().unwrap().into_iter() {
}
Run Code Online (Sandbox Code Playgroud)

然后into_iter(),当值移动到调用线程时,它将正常工作.

当然,您需要构造向量并适当地推送它:

let threads = Arc::new(Mutex::new(Some(Vec::new())));
...
threads.lock().unwrap().as_mut().unwrap().push(handle);
Run Code Online (Sandbox Code Playgroud)

但是,最好的方法是完全删除该Arc<Mutex<..>>层(当然,如果未从其他线程使用此值).

  • 在不稳定的生锈,而不是使用`Option`技巧,你也可以使用[`split_off`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method. split_off)函数或`Vec`上的[`drain`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.drain)函数 (2认同)

Eth*_*han 6

如何从 Arc<Mutex<T>> 获取 T 的所有权?现在可以使用 Arc::try_unwrap 和 Mutex.into_inner() 在 Rust 中无需任何欺骗就可以做到这一点

    let threads = Arc::new(Mutex::new(Vec::new()));

    for _x in 0..100 {
         let handle = thread::spawn(move || {
              println!("{}", _x);
         });

         threads.lock().unwrap().push(handle);
    }

    let threads_unwrapped: Vec<JoinHandle<_>> = Arc::try_unwrap(threads).unwrap().into_inner().unwrap();
    for t in threads_unwrapped.into_iter() {
         t.join().unwrap();
    }
Run Code Online (Sandbox Code Playgroud)

在这个游乐场中尝试一下以进行验证。

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=9d5635e7f778bc744d1fb855b92db178