如何使用Arc <mutex <mystruct <t>&gt;&gt;?

时间:2016-10-14 05:44:39

标签: rust

我需要在线程之间共享一些可变状态。我跟着Rust书的concurrency section,它在线程之间共享一个向量并改变它。

我需要共享最终单形化的通用结构,而不是向量。以下是我正在尝试的一个简单的例子:

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));
}

编译器抱怨以下错误:

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`

我试图理解为什么M需要实现Send,以及实现此目的的恰当方法是什么。

1 个答案:

答案 0 :(得分:8)

  

我试图理解为什么M需要实施Send,...

正如the Send documentation所述:

  

可跨线程边界传输的类型。

如果它不是Send,那么按照定义发送到另一个帖子是不安全的。

您需要的几乎所有信息都是文档中的

  • thread::spawn要求您提供的密码为Send
  • 您正在使用一个闭包,如果它捕获的所有值都是Send,则只有Send。大多数类型的情况都是如此(Send如果他们所做的一切都是Send,而Sync则类似。
  • 您正在抓取data Arc<T>,如果SendT,则Send仅为T
  • SendMutex<U>,如果USend,则仅U
  • MM。因此,Send必须为thread::spawn

此外,请注意'static还要求可调用者为M: 'static + Send + Memory,因此您也需要它。它需要那个因为如果它不需要它,它就不能保证该值在线程的整个生命周期内都会继续存在(这可能会或可能不会过时)产生它的线程。)

  

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

与任何其他约束相同:{{1}}。