Afs*_*ani 4 multithreading closures rust
它是否创建一个新线程然后在新线程中执行该匿名函数?
当我使用闭包时,我注意到许多所有权/借用限制.例如,如果我有Fn(),我不能在闭包内传递一个可变变量,或者它需要用一个包裹Mutex:
fn helloworld(f: &Fn(f64)) {
f(42f64);
}
pub fn main() {
let mut killer = 2;
helloworld(&|n| {
println!("{}", n);
killer += 1;
});
}
Run Code Online (Sandbox Code Playgroud)
如果一个闭包可能不安全,那么场景后面会发生异步或并行的事情,这就是为什么Rust编译器不允许我编译这样的代码.
我可能会感到困惑,因为我来自JavaScript/Python世界,那里的情况完全不同.
DK.*_*DK. 12
这个问题分为两层.
首先,Rust中的闭包只是一个匿名定义的类型,它实现了一个或多个"可调用"特征.例如,这个:
fn main() {
let a = 6;
let closure = |b| {
println!("product is: {}", a * b);
};
closure(7);
}
Run Code Online (Sandbox Code Playgroud)
脱糖成类似于:
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,));
}
Run Code Online (Sandbox Code Playgroud)
注意:上面的代码依赖于不稳定的内部细节,不适用于稳定的编译器.它仅供参考; 你应该不自己使用这种模式.
没有线程涉及,没有任何神奇的事情发生.它们归结为常规函数调用,带有额外的初始"上下文"参数.
这将我们带到第二层,这就是为什么你的特定代码不起作用的原因:因为你告诉编译器禁止它.关于callable的一个关键问题是如何将上下文传递给callable的代码.这是由代表Fn,FnMut以及FnOnce特性(这是在回答解释这个问题什么时候闭合实现FN,FnMut和FnOnce? ).通过采取&Fn(f64),你限制自己只接受需要不可变访问其上下文的闭包.
如果您希望闭包能够改变其上下文,则需要使用FnMut.或者,如果你只需要调用一次闭包,你可以使用FnOnce(虽然不像你在你的例子中那样做的特征对象).