Bog*_*kiy 1 multithreading closures lifetime rust
我可以运行这段代码
fn testf(host: &str) {}
fn start(host: &str) {
testf(host);
testf(host);
}
Run Code Online (Sandbox Code Playgroud)
但出于某种原因,我无法运行这个:
fn testf(host: &str) {}
fn start(host: &str) {
thread::spawn(move || testf(host));
thread::spawn(move || testf(host));
}
Run Code Online (Sandbox Code Playgroud)
因为以下错误
src/server.rs:30:5: 30:18 error: the type `[closure@src/server.rs:30:19: 30:38 host:&str]` does not fulfill the required lifetime
src/server.rs:30 thread::spawn(move || testf(host));
^~~~~~~~~~~~~
note: type must outlive the static lifetime
error: aborting due to previous error
Run Code Online (Sandbox Code Playgroud)
有人可以解释一下,它有什么问题以及如何解决它?
您的闭包捕获字符串切片,因此其环境的生命周期不会超过此切片的生命周期,但thread::spawn()
要求其参数具有静态生存期:
pub fn spawn<F, T>(f: F) -> JoinHandle<T>
where F: FnOnce() -> T,
F: Send + 'static,
T: Send + 'static
Run Code Online (Sandbox Code Playgroud)
(注意F: 'static
要求)
这是必要的,因为当生成的线程thread::spawn()
运行时,可能已经销毁了从中获取切片的字符串.Rust实际上阻止了代码中的错误!
有几种方法可以解决它.
1)最简单的方法是克隆每个线程的字符串:
fn start(host: &str) {
{
let host = host.to_owned();
thread::spawn(move || testf(&host));
}
{
let host = host.to_owned();
thread::spawn(move || testf(&host));
}
}
Run Code Online (Sandbox Code Playgroud)
这样每个线程都会收到自己的字符串副本,当线程本身完成时,该副本将被销毁.
2)如果你知道之前,你的线程应该完成start()
函数结束时,您可以使用第三方librariy像横梁,以引用传递到产生的线程:
extern crate crossbeam;
fn start(host: &str) {
crossbeam::scope(|scope| {
scope.spawn(move || testf(host));
scope.spawn(move || testf(host));
});
}
Run Code Online (Sandbox Code Playgroud)
这种方式start()
将等待,直到两个线程生成scoped()
完成后才返回,确保任何字符串host
指向不会过早地被销毁.
以前这样的功能包含在标准库中,但是它的实现方式被发现是不合理的,所以它被弃用了; 正确替换此功能尚未添加回标准库.
3)甚至另一种选择是使用Arc<String>
在线程之间共享字符串,但这需要在以下之外进行更多重大更改start()
:
use std::sync::Arc;
fn start(host: Arc<String>) {
{
let host = host.clone();
thread::spawn(move || testf(&host));
}
{
let host = host.clone();
thread::spawn(move || testf(&host));
}
}
Run Code Online (Sandbox Code Playgroud)
使用这种方法,你需要将你的字符串保持在一个Arc
(这是一个"原子引用计数"指针),所以这要求你改变调用的代码start()
.克隆可能更好.当然,如果你想分享没有&str
,但&SomeStruct
这里SomeStruct
是大和/或不可复制的,有没有办法避免作用域异Arc
.
归档时间: |
|
查看次数: |
1350 次 |
最近记录: |