thread::spawn
可以使用 thread::spawn
创建线程:
- 线程内部的代码用闭包来执行
main
进程一旦结束,所有子线程也会立刻结束。所以需要先确保子线程都结束,再结束程序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| use std::thread; use std::time::Duration;
fn main() { thread::spawn(|| { for i in 1..10 { println!("hi number {} from the spawned thread!", i); thread::sleep(Duration::from_millis(1)); } });
for i in 1..5 { println!("hi number {} from the main thread!", i); thread::sleep(Duration::from_millis(1)); } }
|
.join()
: 等待线程结束
和其他语言里的 join()
作用一样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| use std::thread; use std::time::Duration;
fn main() { let handle = thread::spawn(|| { for i in 1..5 { println!("hi number {} from the spawned thread!", i); thread::sleep(Duration::from_millis(1)); } });
handle.join().unwrap();
for i in 1..5 { println!("hi number {} from the main thread!", i); thread::sleep(Duration::from_millis(1)); } }
|
线程屏障 Barrier
是用于同步的机制. 类似于初始值非零的 semaphore.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| use std::sync::{Arc, Barrier}; use std::thread;
fn main() { let mut handles = Vec::with_capacity(6); let barrier = Arc::new(Barrier::new(6));
for _ in 0..6 { let b = barrier.clone(); handles.push(thread::spawn(move|| { println!("before wait"); b.wait(); println!("after wait"); })); }
for handle in handles { handle.join().unwrap(); } }
|
线程局部变量
使用 thread_local!
宏初始化线程内部的局部变量,然后在线程内部使用该变量的 with
方法获取变量值。每个新的线程访问它时,都会使用它的初始值作为开始,各个线程中的值彼此互不干扰。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| use std::cell::RefCell; use std::thread;
thread_local!(static FOO: RefCell<u32> = RefCell::new(1));
FOO.with(|f| { assert_eq!(*f.borrow(), 1); *f.borrow_mut() = 2; });
let t = thread::spawn(move|| { FOO.with(|f| { assert_eq!(*f.borrow(), 1); *f.borrow_mut() = 3; }); });
t.join().unwrap();
FOO.with(|f| { assert_eq!(*f.borrow(), 2); });
|
这里,线程对 FOO 的使用方式是借用。我们无法在每个线程里获取 FOO 的独立拷贝最后汇总。
只调用一次的函数(初始化全局变量)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| use std::thread; use std::sync::Once;
static mut VAL: usize = 0; static INIT: Once = Once::new();
fn main() { let handle1 = thread::spawn(move || { INIT.call_once(|| { unsafe { VAL = 1; } }); });
let handle2 = thread::spawn(move || { INIT.call_once(|| { unsafe { VAL = 2; } }); });
handle1.join().unwrap(); handle2.join().unwrap();
println!("{}", unsafe { VAL }); }
|