【发布时间】:2021-08-29 04:36:50
【问题描述】:
让我们从Arc 的规范示例开始
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let msg = Arc::new(Mutex::new(String::new()));
let mut handles = Vec::new();
for _ in 1..10 {
let local_msg = Arc::clone(&msg);
handles.push(thread::spawn(move || {
let mut locked = local_msg.lock().unwrap();
locked.push_str("hello, world\n");
}));
}
for handle in handles {
handle.join().unwrap();
}
println!("{}", msg.lock().unwrap());
}
这会按预期编译和运行。然后我意识到Mutex 可能不必存在于堆上,并开始想知道我是否可以摆脱Arc 并只使用对分配在堆栈上的Mutex 的共享引用。这是我的尝试
use std::sync::Mutex;
use std::thread;
fn main() {
let msg = Mutex::new(String::new());
let mut handles = Vec::new();
for _ in 1..10 {
let local_msg = &msg;
handles.push(thread::spawn(move || {
let mut locked = local_msg.lock().unwrap();
locked.push_str("hello, world\n");
}));
}
for handle in handles {
handle.join().unwrap();
}
println!("{}", msg.lock().unwrap());
}
不过这个不能编译
error[E0597]: `msg` does not live long enough
--> src/main.rs:8:25
|
8 | let local_msg = &msg;
| ^^^^ borrowed value does not live long enough
9 | handles.push(thread::spawn(move || {
| ______________________-
10 | | let mut locked = local_msg.lock().unwrap();
11 | | locked.push_str("hello, world\n");
12 | | }));
| |__________- argument requires that `msg` is borrowed for `'static`
...
20 | }
| - `msg` dropped here while still borrowed
error: aborting due to previous error
For more information about this error, try `rustc --explain E0597`.
error: could not compile `hello`
To learn more, run the command again with --verbose.
编译器抱怨local_msg 没有'static 生命周期。好吧,它没有,所以这个错误是有道理的。但是,这意味着第一个 sn-p 中的变量 let local_msg = Arc::clone(&msg); 具有 'static 生命周期,否则我应该会得到类似的错误。
问题:
-
Arc::clone(&msg)如何获得'static的生命周期?它指向的值在编译时是未知的,并且可能在整个程序退出之前死亡。 - 另外,像
Box和Rc这样的其他堆支持的智能指针呢?它们是否都具有'static生命周期,因为借用检查器确保只要这些指针可见,它们指向的地址就始终有效?
【问题讨论】:
-
"它指向的值在编译时是未知的,并且可能在整个程序退出之前就死掉" - 但它不会在 Arc 本身死掉之前就死掉,这就是重要的.
-
T: 'static并不意味着T会一直存在到程序结束,而是它的所有者可以随心所欲地保留它。为此,T必须包含拥有的数据,例如String并且 如果 它包含引用,那么它们必须具有'static生命周期。
标签: asynchronous rust closures lifetime borrow-checker