【问题标题】:The lifetime of self parameter in Rust when using threads [duplicate]使用线程时 Rust 中 self 参数的生命周期 [重复]
【发布时间】:2019-08-25 08:13:31
【问题描述】:

我正在学习 Rust,我有这个代码:

use std::sync::{Arc, Mutex};
use std::thread::spawn;

pub struct MyText {
    my_text: Mutex<Vec<String>>,
}

pub trait MyTextOptions {
    fn add(&self, t: String);
}

impl MyTextOptions for MyText {
    fn add(&self, text: String) {
        let int_text = Arc::new(self);
        let put_into_my_text = spawn(move || {
            let mut text_feed = int_text.my_text.lock().unwrap();
            text_feed.push(text)
        });
        put_into_my_text.join();
    }
}

当我尝试运行它时,我得到:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src\buffer.rs:37:33
   |
37 |         let int_text = Arc::new(self);
   |                                 ^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 36:5...
  --> src\buffer.rs:36:5
   |
36 | /     fn add(&self, text: String) {
37 | |         let int_text = Arc::new(self);
38 | |         let put_into_my_text = spawn(move || {
39 | |             let mut text_feed = int_text.my_text.lock().unwrap();
...  |
42 | |         put_into_my_text.join();
43 | |     }
   | |_____^
   = note: ...so that the expression is assignable:
           expected &buffer::MyText
              found &buffer::MyText
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `[closure@src\buffer.rs:38:38: 41:10 int_text:std::sync::Arc<&buffer::MyText>, text:std::string::String]` will meet its required lifetime bounds
  --> src\buffer.rs:38:32
   |
38 |         let put_into_my_text = spawn(move || {
   |

在使用线程时,我似乎无法理解 rust 变量的生命周期。不管我用这个函数做什么,我仍然会收到这种类型的错误。

【问题讨论】:

  • 基本上,您在该功能期间借用self。线程可以比该函数更长寿。

标签: rust


【解决方案1】:

通过thread::spawn 生成的线程理论上可以比其父线程寿命更长。如果子线程可以引用来自父线程的数据,则当父线程停止时,这些引用将悬空(无效)。这表示为'static 绑定在给thread::spawn 的闭包上。编译器不理解你join同一函数中的线程这一事实,因此限制仍然成立。

您已经尝试使用Arc(大概是为了解决这个问题),但您正在创建selfArc,这已经是一个参考。因此,您只是将引用放入Arc。该值不满足'static 界限,这就是您收到错误的原因。

有多种方法可以解决此问题,其中很多方法取决于您项目的整体架构。最简单的方法之一是使用crossbeam 中的scoped(或者具体来说,crossbeam_utils):

use crossbeam_utils::thread;

impl MyTextOptions for MyText {
    fn add(&self, text: String) {
        thread::scope(|s| {
            s.spawn(|_| {
                let mut text_feed = self.my_text.lock().unwrap();
                text_feed.push(text)
            });
        }).unwrap();
    }
}

这是一个花哨的辅助函数,实际上通过确保子线程在父线程之前结束,您可以从父范围借用值。

另一种解决方案是将MyText 值放入Arc 中(特别是:按值,而不是按引用)。然后您可以多次克隆此Arc 并将其发送到新线程。但这意味着你不能使用以&amp;self为接收者的方法,而是必须以另一种方式解决。

【讨论】:

  • 谢谢,但是当我这样实现它时,我得到:30 | impl MyTextOptions for MyText { | ^^^^^^^^^^^^^- help: indicate the anonymous lifetime: `&lt;'_&gt;。顺便说一句,我仍在使用 ``` let int_text = Arc::new(self.clone()); ```
  • 这个解决方案不再出现上述错误。
  • The fact that you join the thread in the same function is not understood by the compiler... 为什么...?
猜你喜欢
  • 2019-05-22
  • 2013-07-03
  • 2020-04-20
  • 1970-01-01
  • 2018-08-12
  • 2022-12-13
  • 2019-04-08
  • 1970-01-01
  • 2022-08-22
相关资源
最近更新 更多