当前位置: 首页 > 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!("===============");
}
http://www.lryc.cn/news/448035.html

相关文章:

  • 【L波段差分干涉SAR卫星(陆地探测一号01组)】
  • 第五部分:6---信号的递达
  • 深入解析 ARM64 SOC RK3568的 /proc/interrupts 输出
  • Android常用C++特性之std::unique
  • Redis篇(Java操作Redis)
  • Cypress自动化Github workflow
  • Hbase高阶知识:HBase的协处理器(Coprocessor)原理、使用实例、高级技巧和案例分析
  • 海尔嵌入式硬件校招面试题及参考答案
  • Leetcode基础算法篇|202409(4)贪心算法
  • echarts 导出pdf空白原因
  • 数据结构及基本算法
  • vue3学习记录-computed
  • SQLite3模块使用详解
  • 防火墙详解(三)华为防火墙基础安全策略配置(命令行配置)
  • 假期学习--iOS中的static关键字
  • Maya没有Arnold材质球
  • 面试知识点总结篇三
  • 数据加密标准(DES)详解:原理、步骤及Python实现
  • 每日OJ_牛客_OR59字符串中找出连续最长的数字串_双指针_C++_Java
  • 虚幻引擎UE5如何云渲染,教程来了
  • 使用Python实现图形学光照和着色的光线追踪算法
  • 通过openAI的Chat Completions API实现一个支持追问的ChatGPT功能集成
  • 8,STM32CubeMX配置SPI工程(读取norflash的ID)
  • 【MATLAB源码-第178期】基于matlab的8PSK调制解调系统频偏估计及补偿算法仿真,对比补偿前后的星座图误码率。
  • AIGC学习笔记—minimind详解+训练+推理
  • 计算机毕业设计 在线项目管理与任务分配系统的设计与实现 Java实战项目 附源码+文档+视频讲解
  • 小程序用户截屏事件
  • HashMap为什么线程不安全?如何实现线程安全
  • Python爬虫之requests模块(一)
  • 当微服务中调度返回大数据量时如何处理