gpt4 book ai didi

rust - Arc、thread 和 channel 的借用值不够长

转载 作者:行者123 更新时间:2023-12-03 11:36:29 25 4
gpt4 key购买 nike

我的代码的目标是发送自定义 Data在线程中使用 channel (std::sync::mpsc::channel)。 Data实例由 Manager 创建并引用 Manager .

use std::sync::mpsc;
use std::sync::Arc;
use std::thread;

struct Manager {}

struct Data<'a> {
manager: &'a Manager,
}

impl Manager {
fn new() -> Self {
Self {}
}

fn make(&self) -> Data {
Data { manager: self }
}
}

unsafe impl Send for Manager {}

fn main() {
let manager = Arc::new(Manager::new());
let (tx, _rx) = mpsc::channel();
let mut children = Vec::new();

for id in 0..2 {
let thread_manager = Arc::clone(&manager);
let thread_tx = tx.clone();

let child = thread::spawn(move || {
let msg = thread_manager.make();
thread_tx.send(msg).unwrap();
println!("thread {} finished", id);
});
children.push(child);
}
}
playground
我有一个错误
error[E0597]: `thread_manager` does not live long enough
--> src/main.rs:36:23
|
33 | let thread_tx = tx.clone();
| --------- lifetime `'1` appears in the type of `thread_tx`
...
36 | let msg = thread_manager.make();
| ^^^^^^^^^^^^^^ borrowed value does not live long enough
37 | thread_tx.send(msg).unwrap();
| ------------------- argument requires that `thread_manager` is borrowed for `'1`
38 | println!("thread {} finished", id);
39 | });
| - `thread_manager` dropped here while still borrowed
但我不明白:
  • let manager = Arc::new(Manager::new());创建 Manager 的实例带引用计数器
  • let thread_manager = Arc::clone(&manager);增加 1 个引用计数器,但它是相同的 Manager实例
  • let msg = thread_manager.make();创建 Data引用 Manager

  • 对我来说,消息可能和经理一样有生命周期。
    我哪里错了?
    谢谢
    艾蒂安

    最佳答案

    For me, msg could have same lifetime as manager.


    是的。这意味着 msg只要封闭函数存在:
    let child = thread::spawn(move || {
    // <— thread_manager moved into and owned by the function
    let msg = thread_manager.make();
    thread_tx.send(msg).unwrap();
    println!("thread {} finished", id);
    // <— thread_manager is dropped here so `msg` becomes invalid
    });
    不知道何时实际接收/使用该消息,但很可能是在线程死亡之后。并且 rustc 不能假设管理器的任何其他实例此时将保持事件状态,因此它必须假设它将留下一个悬空引用。
    为什么不 msg只需使用 Arc<Manager> ,甚至是 Weak<Manager> ? (尽管后者在这里似乎不是一个好主意)。
    您可能能够按照您正在尝试的那些思路(甚至没有 Arc 我相信)使用范围线程,但是 stdlib 没有范围,就编译器而言,两者之间没有生命周期关系调用者和 spawn 的内容打电话,他们过着完全独立的生活,可以按任何顺序运行和停止(即使你使用 join )。所以关于线程绑定(bind)生命周期的推理完全是本地的。

    关于rust - Arc、thread 和 channel 的借用值不够长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65641458/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com