Das*_*h83 0 multithreading rust
我正在尝试生成一组给定的线程,并且每个线程执行一个长时间运行的操作.我将一个结构传递给每个工作线程作为给定线程的内部状态.所述结构的集合保存在向量中,Master结构的一部分.
编译器拒绝我将结构的内部成员传递给Arc::new():
use std::thread;
use std::sync::Arc;
struct Worker {
name: String,
}
struct Master {
workers: Vec<Worker>,
}
impl Worker {
fn start(&self) {
println!("My name is {} and I'm working!", self.name);
thread::sleep_ms(100_000);
}
}
impl Master {
pub fn run_test(&mut self) {
for i in 0..10 {
self.workers.push(Worker {
name: String::new() + "Worker" + &i.to_string()
});
}
let mut data = Arc::new(self.workers);
for i in 0..10 {
let local_data = data.clone();
thread::spawn(move || {
local_data[i].start();
});
}
thread::sleep_ms(100_000);
}
}
fn main() {
let mut master = Master { workers: vec![] };
}
Run Code Online (Sandbox Code Playgroud)
错误消息:
error[E0507]: cannot move out of borrowed content
--> <anon>:26:33
|
26 | let mut data = Arc::new(self.workers);
| ^^^^ cannot move out of borrowed content
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?这是惯用的Rust吗?
欢迎来到所有权.
在Rust中,任何单个数据都有一个且只有一个所有者.不要被愚弄Rc和Arc:它们是在单个(不可见)所有者的顶部共享接口.
表达所有权的最简单方式是按价值:
struct Master {
workers: Vec<Worker>
}
Run Code Online (Sandbox Code Playgroud)
在这里,Master拥有一个Vec<Worker>本身拥有多个Worker.
类似地,按值获取参数的函数(fn new(t: T) -> Arc<T>例如)接收其参数的所有权.
这就是问题所在:
Arc::new(self.workers)
Run Code Online (Sandbox Code Playgroud)
意味着你同时:
Master是该公司的所有者workersArc是该公司的所有者workers鉴于一个和一个所有者的统治,这显然是难以处理的.
那么,你如何欺骗并拥有一个单一数据的多个共同所有者?
好吧......用Rc或者Arc!
struct Master {
workers: Arc<Vec<Worker>>
}
Run Code Online (Sandbox Code Playgroud)
现在创建data就像:
let data = self.workers.clone();
Run Code Online (Sandbox Code Playgroud)
这会创建一个新的Arc(只会碰到引用计数).
但这并不是全部.借款系统的核心原则是:别名XOR Mutability.
由于Arc是混叠,它可以防止可变性.你不能再插入工人了self.workers!
有多种解决方案,例如推迟初始化self.workers直到构建向量,但最常见的是使用单元格或互斥体,即Rc<RefCell<T>>或Arc<Mutex<T>>(或Arc<RwLock<T>>).
RefCell并且Mutex是将借用检查从编译时移动到运行时的包装器.这提供了更多的灵活性,但可能导致运行时混乱而不是编译时错误,因此最好用作最后的手段.