【问题标题】:Referencing self in a long-running Rust thread在长时间运行的 Rust 线​​程中引用 self
【发布时间】:2020-07-31 05:55:46
【问题描述】:

我对如何设计这个问题摸不着头脑。基本上,我想实现一个工作池——有点类似于来自the bookThreadPool,但有一点不同。在书中,他们只是传递了一个闭包,让池中的一个线程运行。但是,我希望池中的每个线程都有一些状态。让我解释一下:

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

struct Job {
    x: usize,
}

struct WorkerPool {
    sender: mpsc::Sender<Job>,
    workers: Vec<Worker>,
}

impl WorkerPool {
    fn new(num_workers: usize) -> WorkerPool {
        let mut workers = Vec::with_capacity(num_workers);
        let (sender, receiver) = mpsc::channel();
        let receiver = Arc::new(Mutex::new(receiver));

        for id in 0..num_workers {
            workers.push(Worker::new(id, receiver.clone()));
        }

        WorkerPool { sender, workers }
    }
}

struct Worker {
    id: usize,
    thread: Option<thread::JoinHandle<()>>,
    receiver: Arc<Mutex<mpsc::Receiver<Job>>>,
}

impl Worker {
    fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
        Worker {
            id,
            thread: None,
            receiver,
        }
    }

    fn start(&mut self) {
        self.thread = Some(thread::spawn(move || loop {
            let job = self.receiver.lock().unwrap().recv().unwrap();
            self.add_to_id(job.x);
        }));
    }

    pub fn add_to_id(&self, x: usize) {
        println!("The result is: {}", self.id + x);
    }
}

我的每个Workers 都有一个 id,它的工作是接受一个包含一个数字的 Job,并打印它的 id 加上那个数字(这当然是一个简化版本;在我的真实用例,每个工作人员都有一个 HTTP 客户端和其他一些状态)。在我看来很简单的问题,但显然上面的代码无法编译。

我意识到Worker::start 中的代码不可能工作,因为它正在将self 移动到线程闭包中,同时我试图分配给self

问题是,我还能如何访问线程的“父”结构中的字段?

我能否以某种方式将线程闭包的生命周期限制为结构的生命周期? (很确定答案是否定的,因为闭包必须是'static)。或者反过来,我必须在这里制作'static 的所有内容吗?

【问题讨论】:

    标签: rust


    【解决方案1】:

    不确定您要解决的确切问题。但是您可以通过确保在线程内访问的引用在线程的整个生命周期内保持有效来编译您的代码。使用Arc&lt;Mutex&lt;usize&gt;&gt; 使id 保持有效

    显示了一个编译代码的示例: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=ed750f5ba5db9597efb9b2b80bde2959

        let recv = self.receiver.clone();
        let id = self.id.clone();
        self.thread = Some(thread::spawn(move || loop {
            let job = recv.lock().unwrap().recv().unwrap();
            //self.add_to_id(job.x);
            *id.lock().unwrap() = job.x;
        }));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-13
      • 2011-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多