std::sync::mpsc
,爲何crossbeam又要搞出一套channel呢?首先咱們來看看標準庫中的channel有哪些不足吧
標準庫中channel的不足
-
Receiver不能被clone,是MPSC的channel。理想情況咱們但願能有MPMC的channel -
Sender和Receiver不是 Sync
。 -
在Go語言中,channel通常和 select
語句一塊兒使用,可是標準庫中的channel並不支持select -
有限容量(Bounded)的channel內部實現就是一個簡單的 Mutex<VecDeque<T>>
,性能比Go語言的channel還差 -
有Sender(=Unbouded)和SyncSender(=Bounded)的區分,用起來不統一。
crossbeam中增強版的channel
Mutex<VecDeque<T>>
產生的瓶頸麼,這裏也相似。對於1-3點:(在此以前咱們先簡單講下如何建立crossbeam的channel)
建立channel
use crossbeam_channel::bounded;
// 建立一個容量是5的channel
let (s, r) = bounded(5);
// 5條消息以內都不會阻塞
for i in 0..5 {
s.send(i).unwrap();
}
// 超過5條就會阻塞了
// s.send(5).unwrap();
use crossbeam_channel::unbounded;
// 建立一個無限容量的channel
let (s, r) = unbounded();
// 不會阻塞
for i in 0..1000 {
s.send(i).unwrap();
}
1 支持MPMC
use std::thread;
use crossbeam_channel::bounded;
let (s1, r1) = bounded(0);
let (s2, r2) = (s1.clone(), r1.clone());
// 起一個線程先接受一個消息而後發出一個消息
thread::spawn(move || {
r2.recv().unwrap();
s2.send(2).unwrap();
});
// 發送一個消息而後接受一個消息
s1.send(1).unwrap();
r1.recv().unwrap();
2 Sender和Receiver是Sync
use std::thread;
use crossbeam_channel::bounded;
use crossbeam_utils::thread::scope;
let (s, r) = bounded(0);
scope(|scope| {
// 起一個線程先接受一個消息而後發出一個消息
scope.spawn(|_| {
r.recv().unwrap();
s.send(2).unwrap();
});
// 發送一個消息而後接受一個消息
s.send(1).unwrap();
r.recv().unwrap();
}).unwrap();
3 支持select
select
宏,支持使用
default
分支處理超時等邏輯
use std::thread;
use std::time::Duration;
use crossbeam_channel::unbounded;
let (s1, r1) = unbounded();
let (s2, r2) = unbounded();
thread::spawn(move || s1.send(10).unwrap());
thread::spawn(move || s2.send(20).unwrap());
select! {
recv(r1) -> msg => assert_eq!(msg, Ok(10)),
recv(r2) -> msg => assert_eq!(msg, Ok(20)),
default(Duration::from_secs(1)) => println!("timed out"),
}
小結
本文分享自微信公衆號 - Rust語言中文社區(rust-china)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。微信