use std::collections::VecDeque;
use std::sync::Arc;
use std::sync::Mutex;
use std::thread;
use std::time::Duration;
fn main() {
let queue = Arc::new(Mutex::new(VecDeque::new())); //because of the move keyword to move the thread t into the
let q_clone = queue.clone();
thread::scope(move |s| {
//let q_cl = queue
let t = s.spawn(move || loop {
let item = queue.lock().unwrap().pop_front();
if let Some(item) = item {
dbg!(item);
} else {
thread::park();
}
});
s.spawn(move || {
for i in 1.. {
q_clone.lock().unwrap().push_back(i);
t.thread().unpark();
thread::sleep(Duration::from_secs(1));
}
});
});
}
在第二个线程spawn中,使用了
move
关键字
我有两个问题:
Arc
发生了什么,Arc
提供了一个引用,克隆它只会增加引用计数,所以根据我的说法,引用只需要借用,不需要取得所有权,但是删除移动时会出现错误。t
是否移动到另一个线程中,如果不是,这如何确保线程t
的生命周期小于第二个线程的生命周期。线程不是可以移动的值,
spawn
只给你一个ScopedJoinHandle
,通过它你可以与线程交互。无法保证任何一个线程的寿命都比另一个线程长。
这里的错误与
Arc
根本无关,事实上你也不需要它,但是因为你传递给thread::scope()
的闭包是在你的线程之前运行的,因此t
是它本地的当第二个线程闭包未标记 move
时超出范围,因此这段代码:
use std::collections::VecDeque;
use std::sync::Mutex;
use std::thread;
use std::time::Duration;
fn main() {
let queue = &Mutex::new(VecDeque::new());
thread::scope(|s| {
let t = s.spawn(|| loop {
let item = queue.lock().unwrap().pop_front();
if let Some(item) = item {
dbg!(item);
} else {
thread::park();
}
});
s.spawn(move || {
for i in 1.. {
queue.lock().unwrap().push_back(i);
t.thread().unpark();
thread::sleep(Duration::from_secs(1));
}
});
});
}
确实按照您的预期工作,第二个闭包再次需要
move
,因为否则 t
在使用之前就会被删除。