Multithreading 有没有一种方法可以使锈迹封闭只将一些变量移入其中?
我有一个带有设置的常规Multithreading 有没有一种方法可以使锈迹封闭只将一些变量移入其中?,multithreading,rust,closures,move-semantics,lifetime,Multithreading,Rust,Closures,Move Semantics,Lifetime,我有一个带有设置的常规struct,还有一个额外的变量设置,我想调整和使用它 对于整数范围内的所有可能值,我希望启动一个(作用域)线程,并将此变量设置为该值。根据此值,它们所做的工作略有不同 每个线程都应该能够读取常规设置结构 use crossbeam; // 0.7.3 struct Settings { // ... many fields } const MAX_FEASIBLE_SCORE: u8 = 10; fn example(settings: Settings)
struct
,还有一个额外的变量设置,我想调整和使用它
对于整数范围内的所有可能值,我希望启动一个(作用域)线程,并将此变量设置为该值。根据此值,它们所做的工作略有不同
每个线程都应该能够读取常规设置结构
use crossbeam; // 0.7.3
struct Settings {
// ... many fields
}
const MAX_FEASIBLE_SCORE: u8 = 10;
fn example(settings: Settings) {
crossbeam::scope(|scope| {
for score in 0..MAX_FEASIBLE_SCORE {
scope.spawn(|_| {
let work_result = do_cool_computation(&settings, score);
println!("{:?}", work_result);
});
}
})
.unwrap();
}
fn do_cool_computation(_: &Settings, _: u8) {}
这不会编译:
error[E0373]:闭包可能比当前函数的寿命长,但它借用了当前函数拥有的“score”
-->src/lib.rs:12:25
|
10 |横梁::范围(|范围|{
|----具有类型`&crossbeam_utils::thread::Scope src/lib.rs:12:13
|
12 |/scope.spawn(| | |{
13 | |让工作|结果=做|冷却|计算(&设置,分数);
14 | | println!(“{:?}”,工作结果);
15 | | });
| |______________^
帮助:要强制闭包拥有'score'(和任何其他引用变量)的所有权,请使用'move'关键字
|
12 |范围.繁殖(移动| | |{
| ^^^^^^^^
这将使&settings
无效,因为第一次循环迭代将在移动
闭包中获得设置
的所有权
唯一简单的方法是:
- 将
结构复制到每个线程中(这在我的实际应用程序中相当昂贵)设置
- 在
周围引入一个设置
,这也让人感到有点遗憾弧
是否有一种方法可以绕过这里的引用计数?是否有一种方法可以将
得分
移动到内部闭包中,同时仍然允许引用设置
?是的,可以将一个或一些变量移动到闭包中(而不是全部或无)
是的,这可以用来“规避”引用计数
我在的文档中找到了一个答案,结果证明正是关于这个问题:“从作用域线程作用域中访问堆栈数据”。该页面还有一个比这个问题中的伪代码更清晰的示例
事实证明,您可以:
- 使用
闭包,但通过使用引用对外部作用域中的变量进行隐藏来引用它们,因此使用move
通过引用而不是值来捕获它们:let settings=&settings
crossbeam::scope(|scope| { let settings = &settings; // refer to outer variable by reference for score in 0..MAX_FEASIBLE_SCORE { scope.spawn(move |_| { let work_result = do_cool_computation(settings, score); println!("{:?}", work_result); }); } }) .unwrap();
- 使用普通闭包,仅通过使用
将所需变量隐藏在闭包内来移动它们:let score=score
crossbeam::scope(|scope| { for score in 0..MAX_FEASIBLE_SCORE { scope.spawn(|_| { let score = score; // capture only score let work_result = do_cool_computation(&settings, score); println!("{:?}", work_result); }); } }) .unwrap();
use closure::closure;
let string = "move".to_string();
let x = 10;
let mut y = 20;
let rc = Rc::new(5);
let closure = closure!(move string, ref x, ref mut y, clone rc, |arg: i32| {
...
});
已捕获但未列出的变量默认为已移动。此处略作挑剔,但您并没有真正“规避”任何事情,你都不是在计算引用。@trentcl谢谢!你当然是对的。“规避”在这里可能有点草率。我稍微改变了答案中的书写方式,但如果你有更好的建议让它更清楚,请随意提出(和/或直接编辑答案)。