从该方法中创建的内部线程闭包访问非死亡自我

问题描述 投票:0回答:1

基本上这与这里是同一个问题。但我正在尝试为我的情况找出更合适的解决方案。

这是 MRE。唯一的依赖是

thread-pool = "*"

use thread_pool::*;

fn main() {
    let framework = HandlingFramework{
        name: "Handler".to_string(),
    };
    framework.do_parallel_things()
}

struct HandlingFramework {
    name: String,
}

impl HandlingFramework {
    fn do_parallel_things(&self) {
        let n_virtual_cores = std::thread::available_parallelism().unwrap().get();
        let (thread_sender, threadpool) = ThreadPool::fixed_size(n_virtual_cores);
        for n in 1..10 {
            println!("iteration {n}");
            let _ = thread_sender.send(move || {
                // inside this thread closure I want to create a useful structure
                // each time which is able to reference properties of the
                // handling framework
                println!("self.name {}", self.name)
                // println!("some alternative message making the program runnable")
            });
        }
        threadpool.shutdown();
        threadpool.await_termination();
    }
}

这给出了所描述的编译错误,即

error[E0521]: borrowed data escapes outside of method
  --> src\main.rs:21:15
   |
15 |       fn do_parallel_things(&self) {
   |                             -----
   |                             |
   |                             `self` is a reference that is only valid in the method body
   |                             let's call the lifetime of this reference `'1`
...
21 |               let _ = thread_sender.send(move || {
   |  _____________________^
22 | |                 // inside this thread closure I want to create a structure each time which is able to reference properties of the
23 | |                 // handling framework
24 | |                 println!("self.name {}", self.name)
25 | |             });
   | |              ^
   | |              |
   | |______________`self` escapes the method body here
   |                argument requires that `'1` must outlive `'static`

但是...我能看到的,毫无疑问你能看到的,是编译器不能看到的:因为线程池在方法结束之前等待所有生成的线程的终止,事实上

self
的生命周期在实践中永远不会成为问题。

&self
也是一个不可变的引用。所以我可以看到,实际上在这些闭包中引用框架的有用值永远不会成为问题。

我一直在尝试找出最简单的解决方案,希望避免使用

Arc<Mutex<...
,但不一定*。是否可以通过对一个或多个变量使用特定的生命周期设置来解决这个问题?以我的 Rust 新手水平,我正在与一生作斗争。

如果不行,使用

unsafe
怎么样?那会感觉像是失败。并且
unsafe
不会删除所有编译器保护,而不仅仅是您需要删除的保护吗?


* 事实上,我并不完全确定如何实现这一点。但正如我所说,我怀疑对于这样的案例来说,工程设计太多了。我很可能是错的。

multithreading rust parallel-processing closures
1个回答
0
投票

非常感谢 Jmb 和 ChayimFriedman。

use scoped_thread_pool::*;

fn main() {
    let framework = HandlingFramework{
        name: "Handler".to_string(),
    };
    framework.do_parallel_things()
}

struct HandlingFramework {
    name: String,
}

impl HandlingFramework {
    fn do_parallel_things(&self) {
        println!("hello");
        let n_virtual_cores = std::thread::available_parallelism().unwrap().get();
        // let (thread_sender, threadpool) = ThreadPool::fixed_size(n_virtual_cores);
        let threadpool = Pool::new(n_virtual_cores);
        for n in 1..10 {
            println!("iteration {n}");
            let _ = threadpool.scoped(|scope| {
                scope.execute(move ||{
                    println!("self.name {}", self.name)
                })
            });
        }
        threadpool.shutdown();
    }
}

这个“范围”的东西是某种深层魔法。将调查发生了什么事。

© www.soinside.com 2019 - 2024. All rights reserved.