使用线程时的终身困境 [英] Lifetime woes when using threads

查看:71
本文介绍了使用线程时的终身困境的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很难编译它:

use std::thread::{self, JoinHandle};

struct Foo<'c> {
    foo: &'c str,
}

impl<'c> Foo<'c> {
    fn use_in_another_thread<F>(self, mut cb: F) -> JoinHandle<Foo<'c>>
        where F: FnOnce(&mut Foo),
              F: Send
    {
        thread::spawn(move || {
            cb(&mut self);
            self
        })
    }
}

fn main() {}

据我所知,生命是美好的,但我遇到了错误...

As far as I can see the lifetimes are sound, but I'm getting errors...

error[E0477]: the type `[closure@src/main.rs:12:23: 15:10 cb:F, self:Foo<'c>]` does not fulfill the required lifetime
  --> src/main.rs:12:9
   |
12 |         thread::spawn(move || {
   |         ^^^^^^^^^^^^^
   |
   = note: type must outlive the static lifetime

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/main.rs:14:13
   |
14 |             self
   |             ^^^^
   |
note: first, the lifetime cannot outlive the lifetime 'c as defined on the body at 11:4...
  --> src/main.rs:11:5
   |
11 |       {
   |  _____^ starting here...
12 | |         thread::spawn(move || {
13 | |             cb(&mut self);
14 | |             self
15 | |         })
16 | |     }
   | |_____^ ...ending here
note: ...so that expression is assignable (expected std::thread::JoinHandle<Foo<'c>>, found std::thread::JoinHandle<Foo<'_>>)
  --> src/main.rs:12:9
   |
12 |           thread::spawn(move || {
   |  _________^ starting here...
13 | |             cb(&mut self);
14 | |             self
15 | |         })
   | |__________^ ...ending here
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `Foo<'_>` will meet its required lifetime bounds
  --> src/main.rs:12:9
   |
12 |         thread::spawn(move || {
   |         ^^^^^^^^^^^^^

我不明白错误所指的寿命是-瓶盖本体的寿命? -或为什么它们必须超过静态寿命.

I don't understand what lifetimes the errors are referring to - the lifetime of the closure body? - or why they must outlive the static lifetime.

推荐答案

导致此问题的生存期约束是Thread::spawn中的约束,它要求FnOnce闭包为Send. Send需要'static,这意味着该数据不包含任何非'static数据.您的数据Foo包含借用的str,而不是'static,这使Foo不为'static.因此,您不能跨线程发送Foo.

The lifetime constraint that is causing this problem is the one in Thread::spawn, which requires the FnOnce closure to be Send. Send requires 'static, which means that the data contains no non-'static data. Your data, Foo, contains a borrowed str, which is not 'static, which makes Foo non-'static. As a result, you can't send Foo across threads.

这是为什么?由于Foo包含借位,因此仅在很小的生命周期内有效.如果Rust允许您将Foo的实例发送到另一个线程,那么在它借用的数据变得无效很长时间之后,该线程就可以轻松使用Foo.

Why is this? Since Foo contains a borrow, it is valid for only a small lifetime. If Rust allowed you to send an instance of Foo to another thread, then that thread could easily use Foo long after the data it borrows has become invalid.

您可能会认为这实际上是过于严格的限制,这是正确的.只要您可以向借阅检查器证明线程在某个生存期内终止,就没有理由不允许 local 并行处理.目前,Rust中没有可用于此目的的结构,但是有一些解决该问题的方法,例如此RFC 扩展了Send特征以允许局部并行.

You might think that this is actually overly restrictive, and you'd be right. There's no reason to not allow local parallelism as long as you can prove to the borrow checker that the thread terminates within some lifetime. There are currently no constructs in Rust to do this, but there are some future solutions for this problem, such as this RFC which extends the Send trait to allow local parallelism.

这篇关于使用线程时的终身困境的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆