【crossbeam系列】4 crossbeam-channel:增強版channel

這一期的內容會輕鬆一些,講講crossbeam中的channel。但是有人就要問了在標準庫裏面已經有了 std::sync::mpsc ,爲何crossbeam又要搞出一套channel呢?首先咱們來看看標準庫中的channel有哪些不足吧

標準庫中channel的不足

  1. Receiver不能被clone,是MPSC的channel。理想情況咱們但願能有MPMC的channel
  2. Sender和Receiver不是 Sync
  3. 在Go語言中,channel通常和 select 語句一塊兒使用,可是標準庫中的channel並不支持select
  4. 有限容量(Bounded)的channel內部實現就是一個簡單的 Mutex<VecDeque<T>> ,性能比Go語言的channel還差
  5. 有Sender(=Unbouded)和SyncSender(=Bounded)的區分,用起來不統一。

crossbeam中增強版的channel

首先,不管容量是否有限,Sender類型統一成一種,這樣用起來就很方便。其次對有限容量的channel進行了重寫(還記得上一期咱們講的Deque其實就是爲了消除 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

如今終於不用笨拙地給Receiver端加鎖了~
   
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

提供了相似Go語言功能的 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"),
}
而且其實select內部不單單支持接受消息,也支持發送消息。同時還有更高級的動態select支持~

小結

咱們看到,crossbeam的channel優雅的解決了標準庫中上述的5個問題,看來沒事能夠多用用了~下一期咱們會講一下crossbeam-util和crossbeam-queue,敬請期待。

本文分享自微信公衆號 - Rust語言中文社區(rust-china)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。微信

相關文章
相關標籤/搜索