前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【crossbeam系列】5 crossbeam-util和crossbeam-queue:一些实用的小东西

【crossbeam系列】5 crossbeam-util和crossbeam-queue:一些实用的小东西

作者头像
MikeLoveRust
发布2020-10-23 15:57:22
8620
发布2020-10-23 15:57:22
举报

这一次我们来介绍一下crossbeam-util和crossbeam-queue,中的一些东西和用法。

crossbeam-util

AtomicCell

这个是并发版的std::cell::Cell,可以对&self就起到变更内部值的效果,主要会用到下面三个方法:

use crossbeam_utils::atomic::AtomicCell;

let a = AtomicCell::new(7);

assert_eq!(a.load(), 7);
assert_eq!(a.swap(8), 7);
assert_eq!(a.load(), 8);
a.store(9);
assert_eq!(a.load(), 9);

ShardedLock

这个和std::sync::RwLock功能相同,不过相对来说读会更快而写更慢。大家在实际使用时可以根据业务的特点酌情选择。

use crossbeam_utils::sync::ShardedLock;

let lock = ShardedLock::new(5);

// 读的锁可以同时获取
{
    let r1 = lock.read().unwrap();
    let r2 = lock.read().unwrap();
    assert_eq!(*r1, 5);
    assert_eq!(*r2, 5);
}

// 写的锁只能有一个
{
    let mut w = lock.write().unwrap();
    *w += 1;
    assert_eq!(*w, 6);
}

WaitGroup

这个类似Golang中的sync.WaitGroup,可以用来等待几个线程的工作全部完成。

use crossbeam_utils::sync::WaitGroup;
use std::thread;

// 创建新的等待组
let wg = WaitGroup::new();

for _ in 0..4 {
    // 创建等待组的引用
    let wg = wg.clone();

    thread::spawn(move || {
        // 实际逻辑

        // 解除对等待组的引用
        drop(wg);
    });
}

// 会阻塞直到所有线程完成工作
wg.wait();

注意和std::sync::Barrier不同的是,WaitGroup中的线程数量是动态的。

scope

这个和std::thread比较像,不同点在于能够支持对当前堆栈的引用。比如如果我们想要写如下的代码

let array = [1, 2, 3];
let mut guards = vec![];

for i in &array {
    let guard = std::thread::spawn(move || {
        println!("element: {}", i);
    });

    guards.push(guard);
}

for guard in guards {
    guard.join().unwrap();
}

是会报错的,因为编译器会要求&array具有'static的生命周期。但实际上因为join的部分,所以其实不会有问题,但编译器并不知道。于是就有了scope的用武之地。有了scope可以这么写:

let array = [1, 2, 3];

crossbeam::scope(|scope| {
    for i in &array {
        scope.spawn(move || {
            println!("element: {}", i);
        });
    }
});

是不是有时候比thread要更方便一些呢~

crossbeam-queue

这是并发版的队列,其实可以理解为实现了sendsync的队列。分为容量有限的ArrayQueue

use crossbeam_queue::{ArrayQueue, PushError};

let q = ArrayQueue::new(2); // 指定容量为2

assert_eq!(q.push('a'), Ok(()));
assert_eq!(q.push('b'), Ok(()));
assert_eq!(q.push('c'), Err(PushError('c')));
assert_eq!(q.pop(), Ok('a'));

和容量无限的SegQueue

use crossbeam_queue::{PopError, SegQueue};

let q = SegQueue::new();

q.push('a');
q.push('b');

assert_eq!(q.pop(), Ok('a'));
assert_eq!(q.pop(), Ok('b'));
assert_eq!(q.pop(), Err(PopError));

当然容量无限的代价是需要动态增加容量,这也使得SegQueue的性能会低一些。crossbeam-queue就这些内容了,是不是很简单~

小结

其实util里面还有一些东西这里没有讲,大家可以自己去看看。这期讲的都是一些零碎的小东西。我们的crossbeam系列到这一期就结束了?吗?也许下期还有,敬请期待~

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-10-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Rust语言学习交流 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • crossbeam-util
    • AtomicCell
      • ShardedLock
        • WaitGroup
          • scope
          • crossbeam-queue
          • 小结
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档