我有一些可变状态需要在线程之间共享。我关注了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 implementSend
, ...
因为,如 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
如果T
是Send
. -
T
是Mutex<U>
, 这只是Send
如果U
是Send
. -
U
是M
.因此,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/