thread::spawn 看起来简单,实际上有 move、join、栈大小、不确定顺序等一连串规则。这篇每一条都用真实运行验证:什么时候要 move、不 join 会怎样、顺序真的不确定吗、scope 又好在哪、栈溢出会怎样。
编译:成功
运行(退出码 0):
主线程名 Some("main") 子线程名 None 两个线程 id 不同: true 子线程算出 55
Builder 命名的线程: worker-7 源码:
1 | use std::thread;
2 | fn main() { let v = vec![1, 2, 3]; let h = thread::spawn(|| { println!("{:?}", v); }); h.join().unwrap(); }
编译:失败
error[E0373]: closure may outlive the current function, but it borrows `v`, which is owned by the current function
--> <实验目录>/src/u87b.rs:2:58
|
2 | fn main() { let v = vec![1, 2, 3]; let h = thread::spawn(|| { println!("{:?}", v); }); h.join().unwrap(); }
| ^^ - `v` is borrowed here
| |
| may outlive borrowed value `v`
|
note: function requires argument type to outlive `'static`
--> <实验目录>/src/u87b.rs:2:44
|
2 | fn main() { let v = vec![1, 2, 3]; let h = thread::spawn(|| { println!("{:?}", v); }); h.join().unwrap(); }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `v` (and any other referenced variables), use the `move` keyword
|
2 | fn main() { let v = vec![1, 2, 3]; let h = thread::spawn(move || { println!("{:?}", v); }); h.join().unwrap(); }
| ++++
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0373`.
源码:
1 | use std::thread;
2 | fn main() { let v = vec![1, 2, 3]; let h = thread::spawn(move || { println!("{:?}", v); }); println!("{:?}", v); h.join().unwrap(); }
编译:失败
error[E0382]: borrow of moved value: `v`
--> <实验目录>/src/u87c.rs:2:110
|
2 | fn main() { let v = vec![1, 2, 3]; let h = thread::spawn(move || { println!("{:?}", v); }); println!("{:?}", v); h.join().unwrap(); }
| - ------- - ^ value borrowed here after move
| | | |
| | | variable moved due to use in closure
| | value moved into closure here
| move occurs because `v` has type `Vec<i32>`, which does not implement the `Copy` trait
|
help: consider cloning the value before moving it into the closure
|
2 ~ fn main() { let v = vec![1, 2, 3]; let value = v.clone();
3 ~ let h = thread::spawn(move || { println!("{:?}", value); }); println!("{:?}", v); h.join().unwrap(); }
|
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0382`.Send 的要求见Send 与 Sync。
编译:成功
参数 (): stdout = ['主线程到达末尾(join = false)']
参数 ('join',): stdout = ['主线程到达末尾(join = true)', '子线程跑完了']编译:成功 8 次运行的顺序: ['04123765', '01234567', '01234567', '01234567', '01234567', '01234567', '01324567', '01234567'] (共 3 种不同顺序)
编译:成功
运行(退出码 0):
scope 里两个线程分别改 data 的左右两半:data = [10, 20, 30, 5, 6, 7] 合计 78
spawn + join 一个空线程平均 25 µs(release,2000 次)编译:成功 栈 2048 KiB:退出码 0;stdout='栈 2048 KiB:递归 2000 层成功 → 2000';stderr 末行=[] 栈 512 KiB:被信号 6 终止;stdout='';stderr 末行=['fatal runtime error: stack overflow, aborting'] 栈 256 KiB:被信号 6 终止;stdout='';stderr 末行=['fatal runtime error: stack overflow, aborting'] 栈 64 KiB:被信号 6 终止;stdout='';stderr 末行=['fatal runtime error: stack overflow, aborting']