Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 有没有一种方法可以使锈迹封闭只将一些变量移入其中?_Multithreading_Rust_Closures_Move Semantics_Lifetime - Fatal编程技术网

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谢谢!你当然是对的。“规避”在这里可能有点草率。我稍微改变了答案中的书写方式,但如果你有更好的建议让它更清楚,请随意提出(和/或直接编辑答案)。