Rust `RefCell<;std::string::string>;`无法在线程之间安全地共享?

Rust `RefCell<;std::string::string>;`无法在线程之间安全地共享?,rust,hyper,Rust,Hyper,这是新Q的延续,为了更好地展示 //main.rs //该值最终将在“main”中修改 //http请求应该以其持有的任何“当前”值进行响应。 让mut测试_的闭包:Arc=Arc::new(RefCell::from(“Foo.”to_string()); // ... //HTTP请求的处理程序 //从https://docs.rs/hyper/0.14.8/hyper/service/fn.service_fn.html 设make_svc=make_service_fn(| | u co

这是新Q的延续,为了更好地展示

//main.rs
//该值最终将在“main”中修改
//http请求应该以其持有的任何“当前”值进行响应。
让mut测试_的闭包:Arc=Arc::new(RefCell::from(“Foo.”to_string());
// ...
//HTTP请求的处理程序
//从https://docs.rs/hyper/0.14.8/hyper/service/fn.service_fn.html
设make_svc=make_service_fn(| | u conn | async{
Ok::(服务|请求|异步移动{
if req.version()==version::HTTP_11{
让foo:String=*为_闭包测试_。借用();
确定(响应::新建(主体::from(foo.as_str()))
}否则{
错误(“非HTTP/1.1,中止连接”)
}
}))
});
不幸的是,我得到的
RefCell无法在线程之间安全地共享


错误消息中的第一个错误是,
RefCell
未实现
Sync
。这是设计的,如
Sync
所述:

不同步的类型是那些在一个系统中具有“内部可变性”的类型 非线程安全形式,如单元格和RefCell。这些类型允许 即使通过一个不变的、共享的 参考资料。例如,单元格上的set方法采用&self,因此 只需要共享引用和单元格。该方法不执行任何操作 同步,因此单元格不能同步

因此,在线程之间共享refcell是不安全的,因为您可以通过常规的共享引用引起数据竞争

但是如果你把它包装成
?嗯,问题又很清楚了:

只要T实现发送,Arc就会实现发送和同步 和同步。为什么你不能把一个非线程安全的t型放在一个弧中 确保线程安全?起初,这可能有点违反直觉: 毕竟,圆弧螺纹的安全性不是很重要吗?关键是: Arc使拥有同一个文件的多个所有权成为线程安全的 数据,但它不会为其数据添加线程安全性。考虑 弧。RefCell不同步,如果Arc始终处于发送状态, Arc也可以。但是我们会遇到一个问题: RefCell不是线程安全的;它跟踪借款数量 使用非原子操作

最后,这意味着您可能需要将圆弧与某种类型的圆弧配对 属于std::sync类型,通常为互斥


Arc
将不会
Sync
除非
T
由于同样的原因是
Sync
。鉴于此,您可能应该使用std/tokio
Mutex
,而不是
RefCell

RefCell只能在单线程上工作。您将需要使用类似的互斥锁,但它可以在多个线程上工作。您可以在此处阅读有关互斥的更多信息:

以下是将圆弧移动到闭合中的示例:

use std::sync::{Arc, Mutex};

fn main() {
    let mut test: Arc<Mutex<String>> = Arc::new(Mutex::from("Foo".to_string()));

    let mut test_for_closure = Arc::clone(&test);
    let closure = || async move {
        // lock it so it cant be used in other threads
        let foo = test_for_closure.lock().unwrap();
        println!("{}", foo);
    };
}
使用std::sync::{Arc,Mutex};
fn main(){
让mut测试:Arc=Arc::new(Mutex::from(“Foo.”to_string());
让mut测试_,以确定_closure=Arc::clone(&test);
让闭包=| |异步移动{
//锁定它,使其不能在其他线程中使用
设foo=test_for_closure.lock().unwrap();
println!(“{}”,foo);
};
}

是否克隆Arc?此部分在代码中不可见。请参阅。请将错误复制为问题中的文本。不要将其作为截图:根据观众的屏幕分辨率,图像可能很难阅读,其他有类似问题的人无法搜索。再次非常感谢!还有一些黑魔法,因为现在借来的价值活得不够长。我做了一个跟进Q,如果你想看一看:非常感谢你的详细解释!现在这对我来说更有意义了。我尝试了一个互斥,它更进一步,但有一个不同的错误。如果你想看一看,我在这里做了一个跟进问题: