当前位置: 首页 > news >正文

Rust 实现线程安全的 Lock Free 计数器

完整代码:https://github.com/chiehw/hello_rust/blob/main/crates/counter/src/lib.rs

定义 Trait

Trait 可以看作是一种能力的抽象,和接口有点类似。Trait 还能作为泛型约束条件,作为参数的限制条件。

pub trait AtomicCounter: Send + Sync {type PrimitiveType;fn get(&self) -> Self::PrimitiveType;	// 获取当前计数器的值。fn increase(&self) -> Self::PrimitiveType;	// 自增,并返回上一次的值fn add(&self, count: Self::PrimitiveType) -> Self::PrimitiveType;	// 添加一个数,并返回上一次的值fn reset(&self) -> Self::PrimitiveType;	// 重置计数器fn into_inner(self) -> Self::PrimitiveType;	// 获取内部值
}

简单的测试用例TDD

使用测试驱动开发可以让目标更明确,这里先写个简单的测试案例。

#[cfg(test)]
mod tests {use super::*;fn test_simple<Counter>(counter: Counter)whereCounter: AtomicCounter<PrimitiveType = usize>,	// 使用 Trait 作为泛型约束条件{counter.reset();assert_eq!(0, counter.add(5));assert_eq!(5, counter.increase());assert_eq!(6, counter.get())}#[test]fn it_works() {test_simple(RelaxedCounter::new(10));}
}

亿点细节

直接封装 AtomicUsize

#[derive(Default, Debug)]
pub struct ConsistentCounter(AtomicUsize);impl ConsistentCounter {pub fn new(init_num: usize) -> ConsistentCounter {ConsistentCounter(AtomicUsize::new(init_num))}
}impl AtomicCounter for ConsistentCounter {type PrimitiveType = usize;fn get(&self) -> Self::PrimitiveType {self.0.load(Ordering::SeqCst)}fn increase(&self) -> Self::PrimitiveType {self.add(1)}fn add(&self, count: Self::PrimitiveType) -> Self::PrimitiveType {self.0.fetch_add(count, Ordering::SeqCst)}fn reset(&self) -> Self::PrimitiveType {self.0.swap(0, Ordering::SeqCst)}fn into_inner(self) -> Self::PrimitiveType {self.0.into_inner()}
}

增加测试用例

使用多线程同时对计数器进行操作,然后判断计数的结果是否正确。更多的测试案例请查看【完整代码】

fn test_increase<Counter>(counter: Arc<Counter>)whereCounter: AtomicCounter<PrimitiveType = usize> + Debug + 'static,{println!("[+] test_increase: Spawning {} thread, each with {}", NUM_THREADS, NUM_ITERATIONS);let mut join_handles = Vec::new();// 创建 NUM_THREADS 个线程,同时使用 increase 函数for _ in 0..NUM_THREADS {let counter_ref = counter.clone();join_handles.push(thread::spawn(move || {let counter: &Counter = counter_ref.deref();for _ in 0..NUM_ITERATIONS {counter.increase();}}));}// 等待线程完成for handle in join_handles {handle.join().unwrap();}let count = Arc::try_unwrap(counter).unwrap().into_inner();let excepted_num = NUM_ITERATIONS * NUM_THREADS;println!("[+] test_increase: get count {}, excepted num is {}", count, excepted_num);// 确定 count 正确assert_eq!(count, excepted_num)}

参考教程:

  • 谈谈 C++ 中的内存顺序 (Memory Order):https://luyuhuang.tech/2022/06/25/cpp-memory-order.html#happens-before

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Springboot使用教程
  • c语言:操作符
  • 【远程桌面】Microsoft Remote Desktop 4 mac
  • 景芯2.5GHz A72训练营dummy添加(一)
  • 4.8作业
  • 蓝桥杯 历届真题 双向排序【第十二届】【省赛】【C组】
  • 创建线程的方式
  • VGA显示器字符显示
  • GitHub教程:最新如何从GitHub上下载文件(下载单个文件或者下载整个项目文件)之详细步骤讲解(图文教程)
  • stable-diffusion-webui怎么样增加自己训练的LoRA模型?
  • HTTP/1.0、HTTP/1.1、HTTP/2.0、HTTP3.0的区别
  • 前端开发之el-table(vue2中)固定列fixed滚动条被固定列盖住
  • UniApp 应用发布到苹果商店指南
  • 使用卷积神经网络(CNN)识别验证码
  • 【网站项目】在线办公小程序
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • 2017 年终总结 —— 在路上
  • ECS应用管理最佳实践
  • Facebook AccountKit 接入的坑点
  • IE报vuex requires a Promise polyfill in this browser问题解决
  • Intervention/image 图片处理扩展包的安装和使用
  • leetcode378. Kth Smallest Element in a Sorted Matrix
  • ng6--错误信息小结(持续更新)
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • python大佬养成计划----difflib模块
  • 笨办法学C 练习34:动态数组
  • 模型微调
  • 普通函数和构造函数的区别
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • “十年磨一剑”--有赞的HBase平台实践和应用之路 ...
  • 继 XDL 之后,阿里妈妈开源大规模分布式图表征学习框架 Euler ...
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • #WEB前端(HTML属性)
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (二)Eureka服务搭建,服务注册,服务发现
  • (附源码)springboot家庭财务分析系统 毕业设计641323
  • (接上一篇)前端弄一个变量实现点击次数在前端页面实时更新
  • (每日一问)计算机网络:浏览器输入一个地址到跳出网页这个过程中发生了哪些事情?(废话少说版)
  • (免费领源码)Python#MySQL图书馆管理系统071718-计算机毕业设计项目选题推荐
  • (区间dp) (经典例题) 石子合并
  • (十五)devops持续集成开发——jenkins流水线构建策略配置及触发器的使用
  • (数位dp) 算法竞赛入门到进阶 书本题集
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (杂交版)植物大战僵尸
  • (转)Mysql的优化设置
  • .desktop 桌面快捷_Linux桌面环境那么多,这几款优秀的任你选
  • .DFS.
  • .Net Core中Quartz的使用方法
  • .NET的数据绑定
  • /dev下添加设备节点的方法步骤(通过device_create)
  • :如何用SQL脚本保存存储过程返回的结果集
  • @Import注解详解
  • @requestBody写与不写的情况
  • [100天算法】-目标和(day 79)