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
Multithreading 防锈封闭是如何工作的,它是如何执行封闭的?_Multithreading_Rust_Closures - Fatal编程技术网

Multithreading 防锈封闭是如何工作的,它是如何执行封闭的?

Multithreading 防锈封闭是如何工作的,它是如何执行封闭的?,multithreading,rust,closures,Multithreading,Rust,Closures,它是否创建一个新线程,然后在新线程内执行匿名函数 我注意到,当我处理关闭时,有许多所有权/借款限制。例如,如果我有Fn(),: 如果一个闭包可能是不安全的,那么在幕后会发生异步或并行的事情,这就是为什么Rust编译器不允许我编译这样的代码 我可能会感到困惑,因为我来自一个JavaScript/Python世界,那里的情况完全不同。这个问题有两个层次 首先,Rust中的闭包只是一个匿名定义的类型,它实现了一个或多个“可调用”特性。例如,这: fn main() { let a = 6;

它是否创建一个新线程,然后在新线程内执行匿名函数

我注意到,当我处理关闭时,有许多所有权/借款限制。例如,如果我有
Fn()
,:

如果一个闭包可能是不安全的,那么在幕后会发生异步或并行的事情,这就是为什么Rust编译器不允许我编译这样的代码


我可能会感到困惑,因为我来自一个JavaScript/Python世界,那里的情况完全不同。

这个问题有两个层次

首先,Rust中的闭包只是一个匿名定义的类型,它实现了一个或多个“可调用”特性。例如,这:

fn main() {
    let a = 6;
    let closure = |b| {
        println!("product is: {}", a * b);
    };
    closure(7);
}
被脱糖成类似于:

fn main() {
    let a = 6;
    let closure = {
        struct Closure<'a> {
            a: &'a i32,
        }
        impl<'a> Fn<(i32,)> for Closure<'a> {
            extern "rust-call" fn call(&self, (b,): (i32,)) {
                println!("product is: {}", (*self.a) * b);
            }
        }
        impl<'a> FnMut<(i32,)> for Closure<'a> {
            extern "rust-call" fn call_mut(&mut self, args: (i32,)) {
                self.call(args)
            }
        }
        impl<'a> FnOnce<(i32,)> for Closure<'a> {
            type Output = ();
            extern "rust-call" fn call_once(self, args: (i32,)) {
                self.call(args)
            }
        }
        Closure {
            a: &a,
        }
    };
    FnOnce::call_once(closure, (7,));
}
fn main(){
设a=6;
let闭包={
结构闭包{
外部“锈调用”fn调用(&self,(b,):(i32,)){
println!(“产品是:{},(*self.a)*b);
}
}
恳求{
外部“锈调用”fn调用(和mut self,args:(i32,)){
self.call(args)
}
}
恳求{
类型输出=();
外部“锈调用”fn调用一次(self,args:(i32,)){
self.call(args)
}
}
关闭{
a:&a,
}
};
调用一次(闭包,(7,);
}
注意:上述代码依赖于不稳定的内部细节,无法在稳定的编译器上运行。仅作解释之用;你应该而不是自己使用这种模式

没有线程,也没有什么神奇的事情发生。它们可以归结为带有额外初始“上下文”参数的常规函数调用

这就把我们带到了第二层,这就是您的特定代码无法工作的原因:因为您告诉编译器禁止它。可调用函数的一个关键问题是如何将上下文传递给可调用函数的代码。这表现为
Fn
FnMut
FnOnce
特征(在问题的答案中解释)。通过使用
&Fn(f64)
,您将自己限制为只接受需要对其上下文进行不可变访问的闭包


如果希望闭包能够改变其上下文,则需要使用
FnMut
。或者,如果只需要调用一次闭包,可以使用
FnOnce
(虽然不像您在示例中那样作为trait对象)。

闭包是带有变量捕获的匿名函数,它不是多线程的(除非您要求)。此外,当你说“如果我有
Fn()
,我不能在闭包内传递可变变量,或者它需要用
互斥体
包装”时,你能发布你提到的代码吗?@Boiethios-sure,刚刚用一个链接更新了问题。你需要使用
FnMut
:但我让有更多知识的人用详细的解释来回答。@Boiethios没错,更改为FnMut或使用互斥可以解决问题,但我的问题是,为什么?如果它不是一个单独的线程,为什么传递互斥锁更重要呢?哇,这是一个很好的解释。非常感谢你,DK。
fn main() {
    let a = 6;
    let closure = {
        struct Closure<'a> {
            a: &'a i32,
        }
        impl<'a> Fn<(i32,)> for Closure<'a> {
            extern "rust-call" fn call(&self, (b,): (i32,)) {
                println!("product is: {}", (*self.a) * b);
            }
        }
        impl<'a> FnMut<(i32,)> for Closure<'a> {
            extern "rust-call" fn call_mut(&mut self, args: (i32,)) {
                self.call(args)
            }
        }
        impl<'a> FnOnce<(i32,)> for Closure<'a> {
            type Output = ();
            extern "rust-call" fn call_once(self, args: (i32,)) {
                self.call(args)
            }
        }
        Closure {
            a: &a,
        }
    };
    FnOnce::call_once(closure, (7,));
}