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

标签 rust

我有一些可变状态需要在线程之间共享。我关注了concurrency section 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));
}

编译器报错如下:

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,以及实现它的合适方法是什么。

最佳答案

I'm trying to understand why M would need to implement Send, ...

因为,如 the Send documentation 所述:

Types that can be transferred across thread boundaries.

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

您需要的几乎所有信息都就在文档中:

  • thread::spawn 要求你给它的 callable 是 Send .
  • 你正在使用一个闭包,它只是 Send如果它捕获的所有值都是 Send .大多数类型都是如此(它们是 Send 如果它们的所有组成部分都是 Send ,对于 Sync 也是如此)。
  • 您正在捕获 data ,这是一个 Arc<T> , 这只是 Send如果TSend .
  • T Mutex<U> , 这只是 Send如果USend .
  • UM .因此,M必须是 Send .

此外,请注意 thread::spawn还要求可调用对象为 'static ,所以你也需要它。它需要那个,因为如果它不需要那个,它就无法保证该值将在线程的整个生命周期内继续存在(它可能会或可能不会比产生的线程长寿它)。

..., and what the appropriate way to accomplish this is.

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

关于rust - 如何使用 Arc<Mutex<MyStruct<T>>> 在线程之间共享通用结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40035731/

相关文章:

types - 我如何在 Rust 中惯用地将 bool 转换为 Option 或 Result?

rust - 如何在泛型中指定迭代器类型?

concurrency - 向下移动 Arc Mutex Ncurses 窗口线程仍然没有实现发送

rust - 如何向现有原始类型添​​加构造函数?

rust - 可变地传递一个不变地借用的变量

rust - 无法从另一个 crate 导入模块 - Unresolved 导入

reference - 用于处理对缓冲区的引用的惯用 Rust 方法

rust - 如何根据不同的标准对数据进行排序,而不必复制数据?

rust - 为什么对原语的引用没有隐式取消引用

rust - 如何制作可以反序列化为多种类型之一的 config.rs 字段?