RefCell 替代方案可以是“发送”?

Gue*_*OCs 6 rust

我正在设计一种可以在线程之间发送或不可以发送的类型,具体取决于它是否是自有类型。

这段代码:

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

Cry*_*jar 4

我知道这不是 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)