rust - 多线程学习笔记
2020-02-22 本文已影响0人
国服最坑开发
0x01 最一般的用法
use std::str;
use std::thread;
fn main() {
let mut v = vec![];
for id in 0..5{
let child = thread::spawn(move || {
println!("in child: {}", id);
});
v.push(child);
}
println!("in main : join before");
for child in v {
child.join();
}
println!("in main : join after");
}
结果:
in child: 0
in child: 1
in child: 2
in main : join before
in child: 3
in child: 4
in main : join after
0x02 定制线程参数
use std::str;
use std::thread;
use std::panic;
use std::thread::{Builder, current};
fn main() {
let mut v = vec![];
for id in 0..5 {
let thread_name = format!("child-{}", id);
let size:usize = 3*1024;
let builder = Builder::new().name(thread_name).stack_size(size);
let child = builder.spawn(move ||{
println!("in child : {}", id);
if id == 3 {
// panic::catch_unwind(||{
// panic!("oh no!");
// });
println!("in {} do sm", current().name().unwrap());
}
}).unwrap();
v.push(child);
}
for child in v{
child.join().unwrap();
}
}
结果
in child : 1
in child : 0
in child : 3
in child-3 do sm
in child : 4
in child : 2
0x03 ThreadLocal 线程安全变量
use std::str;
use std::thread;
use std::panic;
use std::thread::{Builder, current};
use std::cell::RefCell;
fn main() {
// create a thread local static var
thread_local!(static FOO:RefCell<u32> = RefCell::new(1));
FOO.with(|f|{
// in main thread : check if 1, and assign to 2
assert_eq!(*f.borrow(), 1);
*f.borrow_mut() = 2;
});
let m = thread::spawn(||{
FOO.with(|f| {
// in sub thread: check 1, and assign to 3
assert_eq!(*f.borrow(),1);
*f.borrow_mut() = 3;
});
});
m.join();
FOO.with(|f|{
// in main thread: check 2
assert_eq!(*f.borrow(), 2);
});
}
结论就是, 没啥输出. 主线程里更新成2后, 子线程的修改, 不影响主线程的内容.
0x04 线程阻塞&打开
park()
: 阻塞线程,unpack()
: 手动激活线程
thread::sleep
当前线程睡一段时间后, 自动后续执行
use std::str;
use std::thread;
use std::panic;
use std::thread::{Builder, current};
use std::time::Duration;
fn main() {
let parked_thread = thread::Builder::new().spawn(|| {
println!("Parking thread");
thread::park();
println!("Thread unparked");
}).unwrap();
thread::sleep(Duration::from_millis(1000));
println!("Unpack the thread" );
parked_thread.thread().unpark();
parked_thread.join().unwrap();
println!("Done!");
}
结果
Parking thread
Unpack the thread
Thread unparked
Done!
0x05 线程锁 Mutex
跨线程更新数据 , 需要对线程进行上锁.
Mutex::lock()
use std::str;
use std::thread;
use std::panic;
use std::thread::{Builder, current};
use std::time::Duration;
use std::sync::{Arc, Mutex};
fn main() {
let mut s = Arc::new(Mutex::new("Hello".to_string()));
let mut v = vec![];
for _ in 0..3 {
let mut s_clone = s.clone();
let child = thread::spawn(move || {
let mut s_clone = s_clone.lock().unwrap();
s_clone.push_str(" Rust!");
});
v.push(child);
}
for c in v {
c.join();
}
println!("{:?}", s);
}
输出
Mutex { data: "Hello Rust! Rust! Rust!" }
0x06 Barrier, 线程等待
use std::str;
use std::thread;
use std::panic;
use std::thread::{Builder, current};
use std::time::Duration;
use std::sync::{Arc, Mutex, Barrier};
fn main() {
let mut handles = Vec::with_capacity(5);
let barrier = Arc::new(Barrier::new(5));
for _ in 0..5 {
let c = barrier.clone();
handles.push(thread::spawn(move || {
println!("before wait");
c.wait();
println!("after wait");
}))
}
for handle in handles {
handle.join().unwrap();
}
}
结果
before wait
before wait
before wait
before wait
before wait
after wait
after wait
after wait
after wait
after wait
0x07 Channel 通信
chanel . recv 会阻塞当前线程
use std::str;
use std::thread;
use std::panic;
use std::thread::{Builder, current};
use std::time::Duration;
use std::sync::{Arc, Mutex, Barrier};
use std::sync::mpsc::channel;
fn main() {
let (tx, rx) = channel();
thread::spawn(move || {
thread::sleep(Duration::from_millis(1000));
tx.send(10).unwrap();
});
let r = rx.recv().unwrap();
assert_eq!(r, 10);
println!("{}", r);
}
结果 : 10