multithreading - Rust 闭包如何工作以及它如何执行闭包?

标签 multithreading rust closures

它会创建一个新线程然后在新线程中执行那个匿名函数吗?

我在处理闭包时注意到许多所有权/借用限制。例如,如果我有 Fn()I cannot pass a mutable variable inside the closure or it needs to be wrapped with a Mutex :

fn helloworld(f: &Fn(f64)) {
    f(42f64);
}

pub fn main() {
    let mut killer = 2;
    helloworld(&|n| {
        println!("{}", n);
        killer += 1;
    });
}

如果闭包可能像那样不安全,那么幕后就会发生一些异步或并行的事情,这就是 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,));
}

Note: the above code relies on unstable, internal details and will not work on a stable compiler. It is provided for explanation only; you should not use this pattern yourself.

不涉及线程,也没有发生任何神奇的事情。它们归结为带有额外初始“上下文”参数的常规函数​​调用。

这将我们带到第二层,这就是为什么您的特定代码不起作用:因为您告诉编译器禁止它。可调用对象的一个​​关键问题是如何将上下文传递给可调用对象的代码。这由 FnFnMutFnOnce 特征表示(在问题 When does a closure implement Fn, FnMut and FnOnce? 的答案中进行了解释)。通过采用 &Fn(f64),您已将自己限制为仅接受需要对其上下文进行不可变访问的闭包。

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

关于multithreading - Rust 闭包如何工作以及它如何执行闭包?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45935100/

相关文章:

c - Visual Studio C 的 _Thrd_create() 和其他线程函数是 Thrd_ C11 函数的实现吗?

arrays - 将字符串数组传递给函数而无需指定 N(编译时间常数)

java - 进行简单回调的最佳方法

c - 在内核中处理线程的正确方法?

c - pthread_cond_broadcast 在 POSIX 中没有忙等待

swift - 原子引用计数和自动引用计数有什么区别?

templates - Velocity 模板宏中的闭包

types - 在火柴臂中创建闭包

java - 停止调用 Oracle 过程的 Java 线程

rust - 如何仅运行标有特定功能的测试并忽略其余功能?