异步#
异步库:tokio, soml
资料
Send 和 Sync#
Send:变量可以安全的发送给另一个线程, Sync:可以在多个线程之前共享,(当且仅当 &T 实现了 Send 时,T 实现了 Send)
Future#
pub trait Future { type Output; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;}
pub enum Poll<T> { Ready(T), Pending,}
开始时,先执行一遍 poll,返回 Poll.Pending
时,执行器不会轮询 poll 来查询状态,而是 poll 函数内部通过 cx.waker().wake()
通知执行器执行一遍 poll。
资料
Channels#
通道原语:
mpsc:多生产者、单消费者 oneshot:单生产者、单消费者 broadcast:多生产者、多消费者 watch:单生产者、多消费者,send 多个,接收一个
在多线程执行者上进行 .await#
future 可以在线程间移动,这意味着
- 不可以使用 Rc,&RefCell
- 不可以使用任何其他没有实现 Send trait 类型 和 没有实现 Sync trait 的引用
- 使用库提供的锁,不可以使用 std::sync 里的 Mutex,
Tokio#
- 总览 https://zhuanlan.zhihu.com/p/460984955
- 初印象 https://zhuanlan.zhihu.com/p/461044853
- 创建异步任务 https://zhuanlan.zhihu.com/p/461384827
- 共享状态 https://zhuanlan.zhihu.com/p/461874095
- 消息传递 https://zhuanlan.zhihu.com/p/462116823
Rust 异步开发#
线程方法#
join
use std::thread;use std::time::Duration;fn main() { let new_thread = thread::spawn(move || { });
// 阻塞,等待线程执行完成 new_thread.join().unwrap();}
线程屏障(Barrier)
在 Rust 中,可以使用 Barrier 让多个线程都执行到某个点后,才继续一起往后执行
以下代码打印 6 条 before wait 后,才打印 6 条 after wait。不会出现 before wait 和 after wait 交替打印
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(); }}
线程间的消息传递#
mpsc:多发送者,单接收者
use std::sync::mpsc;use std::thread;
fn main() { // 创建一个消息通道, 返回一个元组:(发送者,接收者) let (tx, rx) = mpsc::channel();
// 创建线程,并发送消息 thread::spawn(move || { // 发送一个数字1, send方法返回Result<T,E>,通过unwrap进行快速错误处理 tx.send(1).unwrap(); });
// 阻塞,在主线程中接收子线程发送的消息并输出 println!("receive {}", rx.recv().unwrap());
// 不阻塞,没有消息报错 // println!("receive {:?}", rx.try_recv());}
使用通道来 send()
数据,一样要遵循 Rust 的所有权规则:
- 若值的类型实现了 Copy 特征,则直接复制一份该值,然后传输过去
- 若值没有实现 Copy,则它的所有权会被转移给接收端,在发送端继续使用该值将报错