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

Rust 全局变量的最佳实践 lazy_static/OnceLock/Mutex/RwLock

在实际项目开发中,难免需要用到全局变量,比如全局配置信息,全局内存池等,此类数据结构可能在多处需要被使用,保存为全局变量可以很方便的进行修改与读取。

在Rust中,如果只是读取静态变量是比较简单的,比如全局变量是一个usize或者& str等类型的值。如果全局变量是需要初始化产生的就比较复杂了,比如解析一个配置文件,然后把配置文件中的内容赋给全局变量。由于全局变量要被修改,这个全局变量得是可变的,也就是说产生了全局可变变量,而这种方式违反了Rust的设计原则。

一般方法

struct Config {id: u64,
}impl Config {fn new() -> Config {Config {id: 0,}}
}lazy_static::lazy_static! {static ref CACHE: Mutex<Config> = Mutex::new(Config::new());
}fn func1() {CACHE.lock().unwrap().id = 1;
}fn func2() {CACHE.lock().unwrap().id = 2;
}fn func3() -> u64 {return CACHE.lock().unwrap().id;
}fn main() {func1();let id1 = func3();println!("id1 = {}", id1);func2();let id2 = func3();println!("id2 = {}", id2);
}

这种方法一般可以满足需求,但是需要一开始就将变量初始化。
如果有未初始化的字段,可以使用Option等类型搞定。

更好的办法

use std::{sync::{OnceLock, RwLock},thread,time::Duration,
};struct AppData {count: i64,name: String,ptr: usize,
}static APP_SHARE: OnceLock<RwLock<AppData>> = OnceLock::new();fn th_loop1() {let app = APP_SHARE.get().unwrap();loop {{let app2 = app.read().unwrap();println!("th 1 read: {}", app2.count);if (app2.count > 60) {break;}}thread::sleep(Duration::new(1, 0));}println!("th 1 end!!");
}fn th_loop2() {let app = APP_SHARE.get().unwrap();loop {{let mut app2 = app.write().unwrap();app2.count += 1;println!("th 2 write: {}", app2.count);if (app2.count > 80) {break;}}thread::sleep(Duration::new(1, 0));}println!("th 2 end!!");
}fn main() {// 在这里初始化let app = APP_SHARE.get_or_init(|| {RwLock::new(AppData {count: 12 * 4 + 5,name: "abc".to_string(),ptr: (0xFF002403) as usize,})});{let app2 = app.read().unwrap();println!("init ok: {} {} {}", app2.count, app2.name, app2.ptr);}// 线程里面使用let t1 = thread::spawn(th_loop1);let t2 = thread::spawn(th_loop2);t1.join().unwrap();t2.join().unwrap();println!("===============");
}

这里的 AppData 一开始没有初始化,在程序运行时才进行。
能更好适应一般的全局变量需求!!

读多写少的情况,也可以这样:

use std::{cell::{Cell, RefCell},default,sync::{Arc, OnceLock, RwLock},thread,time::Duration,
};
struct T1 {a: i64,b: i64,
}
struct AppData {count: i64,name: String,ptr: usize,count2: RwLock<T1>,
}static APP_SHARE: OnceLock<AppData> = OnceLock::new();fn th_loop1() {let app = APP_SHARE.get().unwrap();loop {{let c2 = app.count2.read().unwrap();println!("th 1 read: {} {}", app.count, c2.a);if (app.count > 60 || c2.a > 10) {break;}}thread::sleep(Duration::new(1, 0));}println!("th 1 end!!");
}fn th_loop2() {let app = APP_SHARE.get().unwrap();loop {{let mut c2 = app.count2.write().unwrap();c2.a += 1;println!("th 2 write: {} {}", app.count, c2.a);if (app.count > 80 || c2.a > 20) {break;}}thread::sleep(Duration::new(1, 0));}println!("th 2 end!!");
}fn main() {// 在这里初始化let app = APP_SHARE.get_or_init(|| AppData {count: 12 * 4 + 5,name: "abc".to_string(),ptr: (0xFF002403) as usize,count2: RwLock::new(T1 { a: 1, b: 2 }),});{println!("init ok: {} {} {}", app.count, app.name, app.ptr);}// 线程里面使用let t1 = thread::spawn(th_loop1);let t2 = thread::spawn(th_loop2);t1.join().unwrap();t2.join().unwrap();println!("===============");
}

相关文章:

Rust 全局变量的最佳实践 lazy_static/OnceLock/Mutex/RwLock

在实际项目开发中&#xff0c;难免需要用到全局变量&#xff0c;比如全局配置信息&#xff0c;全局内存池等&#xff0c;此类数据结构可能在多处需要被使用&#xff0c;保存为全局变量可以很方便的进行修改与读取。 在Rust中&#xff0c;如果只是读取静态变量是比较简单的&…...

【L波段差分干涉SAR卫星(陆地探测一号01组)】

L波段差分干涉SAR卫星&#xff08;陆地探测一号01组&#xff09; L波段差分干涉SAR卫星&#xff08;陆地探测一号01组&#xff09;是我国自主研发的重要卫星系统&#xff0c;以下是对该卫星的详细介绍&#xff1a; 一、基本信息 卫星组成&#xff1a;陆地探测一号01组由A星…...

第五部分:6---信号的递达

目录 信号的递达流程&#xff1a; 信号在什么时候递达&#xff1f; 用户态和内核态&#xff1a; 内核态、用户态在页表的映射关系&#xff1a; 操作系统如何得知当前执行状态是用户态还是内核态&#xff1f; 操作系统如何处理被捕捉的信号&#xff1f; 信号的递达流程&am…...

深入解析 ARM64 SOC RK3568的 /proc/interrupts 输出

在 Linux 系统中&#xff0c;/proc/interrupts 文件提供了系统中断的详细信息&#xff0c;是性能分析和故障排除的重要工具。本文将重点解析 RK3568环境下该文件的输出格式及其背后的结构。 什么是 /proc/interrupts&#xff1f; /proc/interrupts 文件记录了所有中断的信息&…...

Android常用C++特性之std::unique

声明&#xff1a;本文内容生成自ChatGPT&#xff0c;目的是为方便大家了解学习作为引用到作者的其他文章中。 std::unique 是 C 标准库中的一个算法函数&#xff0c;用于移除相邻的重复元素&#xff0c;使每个相邻的元素在容器中保持唯一。它不会真正移除元素&#xff0c;而是通…...

Redis篇(Java操作Redis)

目录 讲解一&#xff1a;简介 讲解二&#xff1a;Jedis Github 一、创建项目、 二、添加依赖 三、配置文件 四、Java连接Redis 五、通过Redis连接池获取连接对象并操作服务器 六、封装JedisUtil对外提供连接对象获取方法 七、Java操作Redis五种数据类型 1. 连接与释放…...

Cypress自动化Github workflow

目录 Workflow .github/workflows/build.yaml jobs build-deploy: .github/wrokflows/execute-tests.yaml 输入参数 jobs restart_failed_dp: seed_data: execute-tests: Docker File docker/Dockerfile.base docker/service-dockerfile.base Deploy deploy/tes…...

Hbase高阶知识:HBase的协处理器(Coprocessor)原理、使用实例、高级技巧和案例分析

目录 第一章 Hbase概述与基础知识 1.1 HBase的架构与数据模型 1.2 什么是协处理器 1.3 协处理器的优势 第二章 协处理器的工作原理 2.1 协处理器的运行机制 2.2 协处理器的注册与监听 2.3 协处理器与RegionServer的交互 第三章 协处理器的类型 3.1 端点协处理器 3.2…...

海尔嵌入式硬件校招面试题及参考答案

使用 QT 的经验及对控件和信号与槽机制的了解 我使用 QT 有一段时间了,在项目开发中积累了较为丰富的经验。 QT 中的控件丰富多样,涵盖了各种常见的界面元素需求。例如按钮、文本框、列表框、进度条等。这些控件具有良好的可定制性,可以通过属性设置、样式表等方式来调整外观…...

Leetcode基础算法篇|202409(4)贪心算法

贪心算法&#xff08;Greedy Algorithm&#xff09;&#xff1a;一种在每次决策时&#xff0c;总是采取在当前状态下的最好选择&#xff0c;从而希望导致结果是最好或最优的算法。 学习链接&#xff1a;leetcode-notes/docs/ch04/04.04/04.04.02-Exercises.md at main datawha…...

echarts 导出pdf空白原因

问题阐述 页面样式&#xff1a; 导出pdf: 导出pdf&#xff0c;统计图部分为空白。 问题原因 由于代码中进行了dom字符串的复制&#xff0c;而echarts用canvas绘制&#xff0c;canvas内部内容不会进行复制&#xff0c;只会复制canvas节点&#xff0c;因此导出pdf空白。 解决…...

数据结构及基本算法

目录 第一章 概论 第一节 引言 第二节 基本概念和常用术语 第三节 算法的描述与分析 第二章 线性表 第一节 线性表定义和基本运算个 一、线性表的逻辑定义 二、线性表的基本运算 第二节 线性表的顺序存储和基本运算的实现 一、线性表的顺序存储 二、顺序表上基本运算…...

vue3学习记录-computed

vue3学习记录-computed 1.为什么要用computed2.使用方法2.1 基本实例2.2 可写计算属性 1.为什么要用computed 写个购物车的案例 <script setup> import { ref, reactive,computed } from "vue" const tableData reactive([{ name: 商品1, price: 10, num: 1…...

SQLite3模块使用详解

目录 一、引言 1.1 SQLite3 简介 1.2 Python sqlite3 模块 二、连接数据库 2.1 导入 sqlite3 模块 2.2 连接数据库 2.3 创建游标对象 三、执行 SQL 语句 3.1 创建表 3.2 插入数据 3.3 查询数据 3.4 更新数据 3.5 删除数据 四、处理查询结果 4.1 fetchall() 4.2…...

防火墙详解(三)华为防火墙基础安全策略配置(命令行配置)

实验要求 根据实验要求配置防火墙&#xff1a; 合理部署防火墙安全策略以及安全区域实现内网用户可以访问外网用户&#xff0c;反之不能访问内网用户和外网用户均可以访问公司服务器 实验配置 步骤一&#xff1a;配置各个终端、防火墙端口IP地址 终端以服务器为例&#xff…...

假期学习--iOS中的static关键字

iOS中的static关键字 OC的static关键字 OC也提供了Static关键字&#xff0c;但是这个static关键字不能用于修饰成员变量&#xff0c;也就是说Static是不被允许修饰实例变量&#xff0c;同时Static关键字也不被允许修饰方法。Static关键字可以修饰全局变量&#xff0c;局部变量…...

Maya没有Arnold材质球

MAYA 没有Arnold材质球_哔哩哔哩_bilibili...

面试知识点总结篇三

一、arm中断流程和函数 ARM 中断流程 中断触发保存上下文中断向量表执行ISR - 清除中断标志恢复上下文返回中断 二、STM32任务间通信有哪些方式 消息队列、 信号量、共享内存、任务通知 三、uboot内存没驱动之前是怎么操作的 硬件初始化内存检测设置内存映射控制台初始化…...

数据加密标准(DES)详解:原理、步骤及Python实现

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storm…...

每日OJ_牛客_OR59字符串中找出连续最长的数字串_双指针_C++_Java

目录 牛客_OR59字符串中找出连续最长的数字串 题目解析 C代码1 C代码2 C代码3 Java代码 牛客_OR59字符串中找出连续最长的数字串 字符串中找出连续最长的数字串_牛客题霸_牛客网 题目解析 双指针&#xff1a; 遍历整个字符串&#xff0c;遇到数字的时候&#xff0c;用双…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

C#学习第29天:表达式树(Expression Trees)

目录 什么是表达式树&#xff1f; 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持&#xff1a; 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...

计算机基础知识解析:从应用到架构的全面拆解

目录 前言 1、 计算机的应用领域&#xff1a;无处不在的数字助手 2、 计算机的进化史&#xff1a;从算盘到量子计算 3、计算机的分类&#xff1a;不止 “台式机和笔记本” 4、计算机的组件&#xff1a;硬件与软件的协同 4.1 硬件&#xff1a;五大核心部件 4.2 软件&#…...