为在多线程环境中调用方法的结构添加生命周期

add lifetime for a struct that invoke method in multi-threading environment

这是我的程序:

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

trait Animal: Send + Sync { fn get_id(&self) -> i32; }

struct Cat {}

impl Animal for Cat {
    fn get_id(&self) -> i32 { return 0; }
}

struct Thread {
    id: i32,
    ptr: Arc<dyn Animal>,
}

impl Thread {
    pub fn multi_threading(&self) {
        let shared_array = Arc::new(Mutex::new([0; 5]));
        let mut handles = vec![];
        for _ in 0..5 {
            let array_ptr = Arc::clone(&shared_array);
            let handle = thread::spawn(move ||
                self.assign(&mut array_ptr.lock().unwrap())
            );
            handles.push(handle);
        }
        for handle in handles {
            handle.join().unwrap();
        }
    }

    pub fn assign(&self, array: &mut MutexGuard<[i32; 5]>) {
        array[self.id as usize] = self.id * self.id + self.ptr.get_id();
    }
}

unsafe impl Send for Thread {}

fn main() {
    let cat = Cat {};
    let ptr_cat = Arc::new(cat);
    let thread = Thread { id: 0, ptr: ptr_cat.clone() };
    thread.multi_threading();
}

struct Thread 定义了一个指向 trait 对象的指针,它的成员方法 multi_threading 除了给一个可以被多个线程访问的数组赋值外什么都不做。

当我编译程序时,错误提示 &self from pub fn multi_threading(&self)

has an anonymous lifetime '_ but it needs to satisfy a 'static lifetime requirement

现在我应该在哪里添加这个 'static 生命周期来满足要求,让程序符合要求?

您可以将实例包装在 Arc 本身中。这样你就可以将它发送到你的线程:

impl Thread {
    pub fn multi_threading(self: &Arc<Self>) {
        let shared_array = Arc::new(Mutex::new([0; 5]));
        let mut handles = vec![];
        for _ in 0..5 {
            let array_ptr = Arc::clone(&shared_array);
            let s = self.clone();
            let handle = thread::spawn(move ||
                s.assign(&mut array_ptr.lock().unwrap())
            );
            handles.push(handle);
        }
        for handle in handles {
            handle.join().unwrap();
        }
    }

    pub fn assign(&self, array: &mut MutexGuard<[i32; 5]>) {
        array[self.id as usize] = self.id * self.id + self.ptr.get_id();
    }
}
...

fn main() {
    let cat = Cat {};
    let ptr_cat = Arc::new(cat);
    let thread = Arc::new(Thread { id: 0, ptr: ptr_cat.clone() });
    thread.multi_threading();
}

Playground

请注意,您不需要 unsafe impl Send for Thread {},因为 Arc 可以安全地共享它。