我正在设计一种可以在线程之间发送或不可以发送的类型,具体取决于它是否是自有类型。
这段代码:
use std::cell::RefCell;
use std::rc::Rc;
pub enum M<'a, T> {
Owned(),
Ref(Rc<RefCell<&'a mut [T]>>)
}
fn main() {
let m: M<'static, u8> = M::Owned();
std::thread::spawn(||{
let m = m;
});
}
Run Code Online (Sandbox Code Playgroud)
给出
error[E0277]: `Rc<RefCell<&mut [_]>>` cannot be sent between threads safely
--> src/main.rs:11:5
|
11 | std::thread::spawn(||{
| _____^^^^^^^^^^^^^^^^^^_-
| | |
| | `Rc<RefCell<&mut [_]>>` cannot be sent between threads safely
12 | | let m = m;
13 | | });
| |_____- within this `[closure@src/main.rs:11:24: 13:6]`
Run Code Online (Sandbox Code Playgroud)
我明白这不是Send因为RefCell是!Send。我认为这是唯一阻止的M事情Send。有没有RefCell替代方案呢Send?
我知道这不是 Send,因为 RefCell 是 !Send。我认为这是阻止 M 发送的唯一原因。
是的,这是正确的。
是否有 RefCell 替代方案即 Send?
当然,至少有两个。如果你只想&mut在另一个线程中,你实际上可以发送它:
#[derive(Debug)]
pub enum M<'a, T> {
Owned(),
Ref(&'a mut [T])
}
fn main() {
let m: M<'static, u8> = M::Owned();
std::thread::spawn(move ||{
println!("{:?}", m);
}).join().unwrap();
}
Run Code Online (Sandbox Code Playgroud)
但是如果你使用例如Rc<RefCell<_>>使你的&mut共享,你可以在多线程上下文中实现相同的事情Arc<Mutex<_>>,正如@Locke已经提到的:
use std::sync::{Arc, Mutex};
#[derive(Debug, Clone)]
pub enum M<'a, T> {
Owned(),
Ref(Arc<Mutex<&'a mut [T]>>)
}
fn main() {
let m: M<'static, u8> = M::Owned();
let m2 = m.clone();
std::thread::spawn(move ||{
println!("{:?}", m2);
}).join().unwrap();
println!("{:?}", m);
}
Run Code Online (Sandbox Code Playgroud)