- 并发(Concurrent):程序的不同部分相互独立执行
- 并行(Parallel):程序不同部分同时执行
1 线程
1.1 基本使用
use std::thread;use std::time::Duration;fn main() {let handle = 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));}handle.join().unwrap();}
thread::spawn()在创建线程失败时会panic,可以用std::thread::Builder::spawn()来创建线程,失败时不会panicthread::sleep()、thread::sleep_ms()、thread::yield_now()thread::current()、thread::park/unpark()(暂停/恢复)1.2 对闭包使用
move
use std::thread;fn main() {let v = vec![1, 2, 3];// 编译通不过:闭包的生存周期可能超过本函数,但是却借用了属于本函数的变量 v// let handle = thread::spawn(|| {// 通过关键字 move,指示将借用的变量的所有权转移到闭包中,闭包外面变量 v 已经失效,不得再使用let handle = thread::spawn(move || {println!("Here's a vector: {:?}", v);});//drop(v);// 即使没有这一句也编译通不过: 这一句只是说明,可能 v 已经失效,但是执行闭包的线程仍然借用着 v,这是不允许的handle.join().unwrap();}
2 通道
2.1 基本使用
use std::thread;use std::sync::mpsc;pub fn main() {let (tx, rx) = mpsc::channel();thread::spawn(move || {let val = String::from("hi");tx.send(val).unwrap();});let received = rx.recv().unwrap();println!("Got: {}", received);}
mpsc表示多个生产者、单个消费者- 接收方法:
recv、try_recv、recv_timeout、recv_deadline、iter、try_iter - 发送端退出后,接收方将返回错误:但通道是缓冲的,发送端退出前发送的所有消息,接收方都可以接收
- 不存在接收方时,发送将失败;存在接收方时,发送一定成功:系统会缓存发送的内容,不限制缓存数量
- 被发送内容的所有权将转移到发送方法中!!!
- 异步通道:
mpsc::channel(),缓存数量无上限 - 同步通道:
mpsc::sync_channel(),必须指定一个缓存数量上限,通道满时发送方发送操作将阻塞; -
2.2 使用多个发送端
调用发送方的
clone方法可以克隆出一个新的发送端,多个发送端可以并发工作
pub fn main2() {let (tx, rx) = mpsc::channel();let tx1 = mpsc::Sender::clone(&tx);// 这样写也是正确的// let tx1 = tx.clone();thread::spawn(move || {let vals = vec![String::from("hi"),String::from("from"),String::from("the"),String::from("thread"),];for val in vals {tx1.send(val).unwrap();thread::sleep(Duration::from_secs(1));}});thread::spawn(move || {let vals = vec![String::from("more"),String::from("messages"),String::from("for"),String::from("you"),];for val in vals {tx.send(val).unwrap();thread::sleep(Duration::from_secs(1));}});for received in rx {println!("Got: {}", received);}}
3 共享状态
3.1 Mutex<T>
use std::sync::Mutex;fn main() {let m = Mutex::new(5);{let mut num = m.lock().unwrap();*num = 6;}println!("m = {:?}", m);}
- 创建:
Mutex::new(),这是一个泛型关联方法,可封装任意类型 - 获取封装的资源
use std::sync::{Mutex, Arc};use std::thread;fn main() {let counter = Arc::new(Mutex::new(0));// 用 Arc<T> 封装 Mutex<T>let mut handles = vec![];for _ in 0..10 {let counter = Arc::clone(&counter);// 克隆let handle = thread::spawn(move || {let mut num = counter.lock().unwrap();// Mutex<T> 实现了内部可变性,通过不可变的 counter 可以改变内部封装的值*num += 1;});handles.push(handle);}for handle in handles {handle.join().unwrap();}println!("Result: {}", *counter.lock().unwrap());}
