如何使用Arc <Mutex <MyStruct <T >>>在线程之间共享通用结构?

w.b*_*ian 3 rust

我有一些可变的状态,我需要在线程之间共享.我按照Rust书的并发部分,它在线程之间共享一个向量并对其进行变异.

我需要共享最终单形化的通用结构,而不是向量.这是我正在尝试的一个提炼的例子:

use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use std::marker::PhantomData;

trait Memory {}

struct SimpleMemory;

impl Memory for SimpleMemory {}

struct SharedData<M: Memory> {
    value: usize,
    phantom: PhantomData<M>,
}

impl<M: Memory> SharedData<M> {
    fn new() -> Self {
        SharedData {
            value: 0,
            phantom: PhantomData,
        }
    }
}

fn main() {
    share(SimpleMemory);
}

fn share<M: Memory>(memory: M) {
    let data = Arc::new(Mutex::new(SharedData::<M>::new()));

    for i in 0..3 {
        let data = data.clone();
        thread::spawn(move || {
            let mut data = data.lock().unwrap();
            data.value += i;
        });
    }

    thread::sleep(Duration::from_millis(50));
}
Run Code Online (Sandbox Code Playgroud)

编译器抱怨以下错误:

error[E0277]: the trait bound `M: std::marker::Send` is not satisfied
  --> src/main.rs:37:9
   |
37 |         thread::spawn(move || {
   |         ^^^^^^^^^^^^^
   |
   = help: consider adding a `where M: std::marker::Send` bound
   = note: required because it appears within the type `std::marker::PhantomData<M>`
   = note: required because it appears within the type `SharedData<M>`
   = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Mutex<SharedData<M>>`
   = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<std::sync::Mutex<SharedData<M>>>`
   = note: required because it appears within the type `[closure@src/main.rs:37:23: 40:10 data:std::sync::Arc<std::sync::Mutex<SharedData<M>>>, i:usize]`
   = note: required by `std::thread::spawn`
Run Code Online (Sandbox Code Playgroud)

我试图理解为什么M需要实现Send,以及实现这一目标的适当方法是什么.

DK.*_*DK. 8

我想了解为什么M需要实施Send,......

因为,正如指出Send文件:

可以跨线程边界传输的类型.

如果不是Send,根据定义发送到另一个线程是不安全的.

几乎所有你需要的信息是正确的有在文档中:

  • thread::spawn需要你给它的可调用Send.
  • 你正在使用一个闭包,只有Send当它捕获的所有值都是Send.大多数类型的情况都是如此(Send如果它们是由它们组成的Send,那么它们也是如此Sync).
  • 你正在捕捉data,这是一个Arc<T>,只有Send当它TSend.
  • T是一个Mutex<U>,只有Send当它USend.
  • UM.因此,M必须Send.

另外,请注意thread::spawn也要求可调用者'static,所以你也需要它.它需要它,因为如果它不需要它,它不能保证该值将在该线程的整个生命周期中继续存在(这可能会或可能不会比生成它的线程更长).

......,以及实现这一目标的适当方法是什么.

与任何其他约束相同:M: 'static + Send + Memory.

  • 我很感谢您的回答,但这意味着我没有尽职调查。无论您是否喜欢,当您为该标签提供答案时,您都可以代表社区。 (3认同)
  • 关于 `Send + 'static` 约束的令人困惑的方面是,在 Rust 书中,他们包装了一个 `Vec`,乍一看似乎没有 `'static` 生命周期,因为它是在 `main` 中定义的方法。经过进一步检查,它是“静态的”,因为它是一个字面值。这对每个人来说都不是很明显。当我最初添加 `Send` 约束时,它抱怨它需要是 `'static`,它似乎无视示例所传达的内容,因此是问题。你回答的居高临下的语气是没有根据的,并且对 Rust 社区的反映很差。 (2认同)
  • @w.brian 至于我的“语气”,恐怕这在你的脑海中:如果我想居高临下,我就不会费心去查看每个特定文档页面的链接,这样你就可以关注我的更容易推理。此外,我觉得你为了一个人的“语气”而诋毁整个社区是冒犯和小气的。不管我是谁,这个社区都有一些我见过的最有帮助、最热情和最勤奋的志愿者。如果你想和某人有问题,就和 *me.* (2认同)