如何使用 Arc> 在线程之间共享通用结构?
我有一些需要在线程之间共享的可变状态.我遵循了 Rust 书中的 并发部分,它在线程和线程之间共享一个向量改变它.
I have some mutable state I need to share between threads. I followed the concurrency section of the Rust book, which shares a vector between threads and mutates it.
我需要共享一个最终单态化的通用结构,而不是向量.这是我正在尝试的一个蒸馏示例:
Instead of a vector, I need to share a generic struct that is ultimately monomorphized. Here is a distilled example of what I'm trying:
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
, and what the appropriate way to accomplish this is.
我试图理解为什么
M
需要实现Send
, ...
I'm trying to understand why
M
would need to implementSend
, ...
因为,正如 Send
文档 所述:
Because, as stated by the Send
documentation:
可以跨线程边界传输的类型.
Types that can be transferred across thread boundaries.
如果不是Send
,根据定义发送到另一个线程是不安全的.
If it's not Send
, it is by definition not safe to send to another thread.
您需要的几乎所有信息就在那里在文档中:
Almost all of the information you need is right there in the documentation:
-
thread::spawn
需要可调用的你让它成为Send
. - 您正在使用闭包,如果它捕获的所有值都是
Send
,则它仅是Send
.对于大多数类型而言,这通常是正确的(如果它们由Send
组成,则它们是Send
,对于Sync
也是如此). - 您正在捕获
数据
,这是一个Arc
,如果T
是Send
,则它只是Send
. -
T
是一个Mutex代码>
,如果U
是Send
,它只是Send
. -
U
是M
.因此,M
必须是Send
.
-
thread::spawn
requires the callable you give it to beSend
. - You're using a closure, which is only
Send
if all the values it captures areSend
. This is true in general of most types (they areSend
if everything they're made of isSend
, and similarly forSync
). - You're capturing
data
, which is anArc<T>
, which is onlySend
ifT
isSend
. -
T
is aMutex<U>
, which is onlySend
ifU
isSend
. -
U
isM
. Thus,M
must beSend
.
此外,请注意 thread::spawn
还要求可调用对象为 'static
,因此您也需要这样做.它需要那个,因为如果它不需要那个,它就不能保证该值将在线程的整个生命周期内继续存在(这可能会也可能不会超过产生它).
In addition, note that thread::spawn
also requires that the callable be 'static
, so you need that too. It needs that because if it didn't require that, it'd have no guarantee that the value will continue to exist for the entire lifetime of the thread (which may or may not outlive the thread that spawned it).
...,以及实现此目的的适当方法是什么.
..., and what the appropriate way to accomplish this is.
与任何其他约束相同的方式:M: 'static + Send + Memory
.
Same way as any other constraints: M: 'static + Send + Memory
.