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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/801255.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 特殊文件属性命令chattr和lsattr

特殊文件属性命令 chattr 和 lsattr chattr 和 lsattr 是有关数据安全的命令&#xff1a; 1&#xff09;chattr作用及语法 a.命令作用&#xff1a; 给 文件或目录 加锁&#xff0c;不让别人修改和删除 b.命令语法&#xff1a; chattr 选项 文件 c.选项属性&#xff1a…

CDN加速原理那些事

名词解释 CNAME记录&#xff08;CNAME record&#xff09; CNAME即别名( Canonical Name )&#xff1b;可以用来把一个域名解析到另一个域名&#xff0c;当 DNS 系统在查询 CNAME 左面的名称的时候&#xff0c;都会转向 CNAME 右面的名称再进行查询&#xff0c;一直追踪到最后…

初探 Spring Boot 源码:揭秘其高效魔法

Spring Boot 作为当今 Java 世界中最受欢迎的框架之一&#xff0c;以其简化配置和快速部署的能力赢得了开发者的广泛赞誉。但是&#xff0c;你是否曾经好奇过&#xff0c;是什么让 Spring Boot 如此高效和强大&#xff1f;本文将带你深入 Spring Boot 的源码&#xff0c;揭示其…

js str字符串和arr数组互相转换

js str字符串和arr数组互相转换 字符串转为数组 1、split()方法 返回的是原字符串的数组 var str "hello"; var arr str.split(""); console.log(arr); //输出["h", "e", "l", "l", "o"]2、Ar…

创建型模式--4.抽象工厂模式【弗兰奇一家】

1. 奔向大海 在海贼世界中&#xff0c;位于水之都的弗兰奇一家是由铁人弗兰奇所领导的以拆船为职业的家族&#xff0c;当然了他们的逆向工程做的也很好&#xff0c;会拆船必然会造船。船是海贼们出海所必备的海上交通工具&#xff0c;它由很多的零件组成&#xff0c;从宏观上看…

算法:完全背包问题dp

文章目录 一、完全背包问题的特征二、定义状态三、状态转移四、降维优化五、参考例题5.1、Acwing&#xff1a;3.完全背包问题5.2、Acwing&#xff1a;900. 整数划分 一、完全背包问题的特征 完全背包问题是动态规划中的一种经典问题&#xff0c;它的主要特征可以总结如下&…

LeetCode热题Hot100 - 删除链表的倒数第N个结点

一刷~ 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 思路&#xff1a; 用两个指针&#xff0c;第一个指针先往前走n步&#xff08;注意起始点不是head&#xff09;&#xff0c;然后第二个指针和第一个指针一起移动&#xff0c;当第一…

[HackMyVM]靶场Flossy

难度:Medium kali:192.168.56.104 靶机:192.168.56.142 端口扫描 ┌──(root㉿kali2)-[~/Desktop] └─# nmap 192.168.56.142 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-04-01 21:01 CST Nmap scan report for 192.168.56.142 Host is up (0.00018s latency).…

浏览器的几种存储方式

浏览器的几种存储方式&#xff08;图表形式&#xff09; 存储方式特点应用场景示例有效期容量是否共享安全性Cookie存储少量数据&#xff0c;例如用户偏好、登录状态等用户认证、个性化设置登录状态、语言偏好会话或永久4KB同源中等Local Storage️永久存储数据&#xff0c;同…

从0开始搭建基于VUE的前端项目(四) Vue-Router的使用与配置

版本 vue-router 3.6.5 (https://v3.router.vuejs.org/zh/) 安装 安装要指定版本&#xff0c;默认安装的4版本的 npm install vue-router3.6.5代码实现 在src目录下创建router目录 router/index.js import Vue from vue import Router from vue-routerVue.use(Router)con…

Nginx入门 -- 解析Nginx中的基本概念:Keepalive

引言&#xff1a; Nginx是一款流行的开源Web服务器软件&#xff0c;被广泛用于构建高性能的Web服务器和反向代理。在Nginx中&#xff0c;Keepalive是一个基本概念&#xff0c;它在网络连接中起到重要的作用。本文将深入探讨Keepalive的工作原理和在Nginx中的应用。 1.Keepaliv…

A5 STM32_HAL库函数 之 CAN通用驱动程序所有函数的介绍及使用

A5 STM32_HAL库函数 之 CAN通用驱动程序所有函数的介绍及使用 1 CAN通用驱动程序所有函数预览1.1 HAL_CAN_Init1.2 HAL_CAN_ConfigFilter1.3 HAL_CAN_DeInit1.4 HAL_CAN_MspInit1.5 HAL_CAN_MspDeInit1.6 HAL_CAN_Transmit1.7 HAL_CAN_Transmit_IT1.8 HAL_CAN_Receive1.9 HAL_C…

fssh挂载远程服务器目录

fssh挂载远程服务器目录 1、服务器自动登录 1.1 生成SSH 密钥对 ssh-keygen -t rsa这个命令会生成一个私钥(默认保存在 ~/.ssh/id_rsa)和一个公钥(默认保存在 ~/.ssh/id_rsa.pub)。 你可以通过 -f 参数指定一个不同的文件名和路径来保存这些密钥。 会要求输入名称和密码…

聊聊Linux内核中内存模型

介绍 在Linux中二进制的程序从磁盘加载到内存&#xff0c;运行起来后用户态是使用pid来唯一标识进程&#xff0c;对于内核都是以task_struct表示。二进制程序中的数据段、代码段、堆都能提现在task_struct中。每一个进程都有自己的虚拟地址空间&#xff0c;虚拟地址空间包含几…

【2024】Prometheus通过node_exporter都监控了什么

我们通过prometheus进行监控,通过node_exporter进行Linux系统的监控。 那么我们通过node_exporter都监控了什么? 目录 常用指标CPU相关内存相关磁盘相关网络相关其他指标常用监控告警案例:cpu案例:内存案例:磁盘案例:网络案例:常用指标 Prometheus通过node_exporter可以…

交换机虚拟化技术

1、思科虚拟化技术&#xff1a; &#xff08;1&#xff09;stackwise&#xff1a;堆叠&#xff0c;一般用于盒式交换机的场景 ①原理&#xff1a;可以将多台物理设备逻辑的虚拟成一台大的设备 ②冗余交换机管理引擎&#xff1a; 三种模式&#xff1a; 1&#xff09;RPR&am…

stack和queue的使用

前言 前面我们对string、vector、list做了介绍并对底层进行了实现&#xff01;本期我们继续来介绍STL容器&#xff0c;stack和queue&#xff01; 本期内容介绍 stack 常用接口的介绍 queue 常用接口的介绍 什么是stack? 这里的栈和我们C语言实现的数据结构的那个栈功能是一样…

向上向下采样

在数字图像处理中&#xff0c;向上采样&#xff08;upsampling&#xff09;和向下采样&#xff08;downsampling&#xff09;是两种常见的操作&#xff0c;用于改变图像的分辨率。 向上采样&#xff08;Upsampling&#xff09;&#xff1a; 向上采样是指增加图像的分辨率&…

leetcode代码记录(最长连续递增序列

目录 1. 题目&#xff1a;2. 我的代码&#xff1a;小结&#xff1a; 1. 题目&#xff1a; 给定一个未经排序的整数数组&#xff0c;找到最长且 连续递增的子序列&#xff0c;并返回该序列的长度。 连续递增的子序列 可以由两个下标 l 和 r&#xff08;l < r&#xff09;确定…

如何查看当前python环境的安装路径

起因&#xff1a;在查看python安装路径时&#xff0c;由于环境变量未添加&#xff0c;导致直接用python无法查看&#xff0c;但是pip又可用。因此找到另外一种代替方法。 利用pip show 库 pip show numpy