rust引用-借用机制扩展
rust引用-借用机制还是有限制的,比如我们要在多次函数调用中修改参数、跨线程传递参数并发修改的场景,单纯使用引用-借用机制就不灵了(这种场景和引用-借用设计思想是冲突的)。这时需要借助rust提供的Rc、Arc、Cell、RefCell对机制来扩展默认的引用借用机制。
慢慢品味,std库里提供的很多实现,都是围绕引用-借用机制展开的;默认的引用-借用机制适合80%的场景,20%的场景还是需要额外的机制来扩展的(引入额外的性能开销,可能其中的15%可以通过优化设计避免)。
1、线程内
use std::rc::Rc;
use std::cell::RefCell;fn main() {println!("Hello, world!");let mut param = Param::default();param.name = "xiao ming".to_string();let rc_param = Rc::new(param);//Rc自带引用计数,可clone多个传给给函数作为参数,超出作用域引用计数减一至零是自动销毁//Rc不能跨线程,要跨线程使用需要改为Arc+Mutexlet rc1 = rc_param.clone();let rc2 = rc_param.clone();let rc3 = rc_param.clone();println!("{}", rc1.name);new_value_fn1(rc2);new_value_fn2(rc3);//如果要在函数中修改参数的值,需要使用Rc+RecCelllet mut param2 = Param::default();param2.name = "小红".to_string();let rc_refcell_param = Rc::new(RefCell::new(param2));let rc_rec_p1 = rc_refcell_param.clone();let rc_rec_p2 = rc_refcell_param.clone();new_value_refcell_fn1(rc_rec_p1);new_value_refcell_fn2(rc_rec_p2);println!("{}", rc_refcell_param.borrow().name); //小红-fn1-fn2
}fn new_value_fn1(param: Rc<Param>){println!("from fn1: {}", param.name);//不让修改,这能引用//param.is_valid = false;
}
fn new_value_fn2(param: Rc<Param>){println!("from fn2: {}", param.name);
}fn new_value_refcell_fn1(param: Rc<RefCell<Param>>){let mut p = param.borrow_mut();let new_name = p.name.clone() + "-fn1";p.name = new_name;p.is_valid = true;
}fn new_value_refcell_fn2(param: Rc<RefCell<Param>>){let mut p = param.borrow_mut();let new_name = p.name.clone() + "-fn2";p.name = new_name;
}struct Param{name: String,age: i32,is_valid: bool,
}impl Default for Param{fn default () -> Self{Self{name: "".to_string(),age: 20,is_valid: true,}}
}
2、跨线程
use std::thread::spawn;
use std::sync::Arc;let mut thread_p1 = Param::default();thread_p1.name = String::from("thread param");let t1 = spawn(move ||{println!("in sub thread t1:{}", thread_p1.name);});//变量thread_p1因为有非Copy类型String,只能在一个线程闭包内使用,如果开启线程2编译报错//let t2 = spawn(move ||{// println!("in sub thread t2:{}", thread_p1.name);//});t1.join().unwrap();//t2.join().unwrap();
我们定义一个变量,要在多个线程闭包内使用,需要引入Arc:
let mut thread_p1 = Param::default();thread_p1.name = String::from("thread param");let thread_param = Arc::new(thread_p1);let thread1_param = thread_param.clone();//clone一个跨线程的引用计数变量给线程1用let thread2_param = thread_param.clone();//clone一个跨线程的引用计数变量给线程2用let t1 = spawn(move ||{println!("in sub thread t1:{}", thread1_param.name);});let t2 = spawn(move ||{println!("in sub thread t2:{}", thread2_param.name);});t1.join().unwrap();t2.join().unwrap();
如果我们还要在线程内修改变量,则需要Mutex介入:
let mut thread_p1 = Param::default();thread_p1.name = String::from("thread param");let thread_param = Arc::new(Mutex::new(thread_p1));//创建跨线程传递的可读性对象let thread1_param = thread_param.clone();//clone一个给线程1用let thread2_param = thread_param.clone();//clone一个给线程2用let t1 = spawn(move ||{let mut v1 = thread1_param.lock().unwrap();//线程1使用thread1_param,先调用lock获取对象,在作用域内是独占的,其他线程不能并行使用v1.name = v1.name.clone() + "__" + "t1";println!("in sub thread t1:{}", v1.name);});let t2 = spawn(move ||{let mut v2 = thread2_param.lock().unwrap();//线程2使用thread2_param,先调用lock获取对象,在作用域内是独占的,其他线程不能并行使用v2.name = v2.name.clone() + "__" + "t2";println!("in sub thread t2:{}", v2.name);});t1.join().unwrap();t2.join().unwrap();let v3 = thread_param.lock().unwrap();//验证两个子线程执行情况 p.name is thread param__t2__t1println!("p.name is {}", v3.name);
抛开执行开销,至少其他语言可做的事情,rust也可做到了,理论上可以平行翻译其他语言实现的模块实现。
相关文章:
rust引用-借用机制扩展
rust引用-借用机制还是有限制的,比如我们要在多次函数调用中修改参数、跨线程传递参数并发修改的场景,单纯使用引用-借用机制就不灵了(这种场景和引用-借用设计思想是冲突的)。这时需要借助rust提供的Rc、Arc、Cell、RefCell对机制…...
JVM的工作流程
目录 1.JVM 简介 2.JVM 执行流程 3. JVM 运行时数据区 3.1 堆(线程共享) 3.3 本地方法栈(线程私有) 3.4 程序计数器(线程私有) 3.5 方法区(线程共享) 4.JVM 类加载 ① 类…...
kibana配置 dashbord,做可视化展示
一、环境介绍 这里我使用的kibana版本为7.17版本。 语言选择为中文。 需要已经有es,已经有kibana,并且都能正常访问。 二、背景介绍 kibana的可视化界面,可以配置很多监控统计界面。非常方便,做数据的可视化展示。 这篇文章&…...
前后端分离项目Docker部署指南(下)
目录 前言: 一.安装nginx 创建目录 上传nginx.conf至/data/nginx/conf文件夹中 运行启动容器 上传静态资源文件 编辑 访问结果 前言: 在上一篇博客中,我们深入探讨了如何使用Docker部署一个前后端分离的项目中的后端部分。我们构建…...
算法->位运算
有关位运算的操作符 >> <<&|^~ 常见位运算操作 给定一个数,确定它的二进制中第x位是0还是1 (n >> x) & 1; 将一个数n的二进制中第x位修改为1 n | (1 << x) 将一个数n的二进制中第x位修改为0 n & (~(1 << x)) 提…...
【Python】成功解决ModuleNotFoundError: No module named ‘matplotlib‘
【Python】成功解决ModuleNotFoundError: No module named ‘matplotlib’ 🌈 个人主页:高斯小哥 🔥 高质量专栏:Matplotlib之旅:零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程👈…...
centos7中python3.10找不到openssl解决方案
如果有用其他方法安装了其他版本openssl,记得卸载其他的openssl,删除其他的openssl相关文件。 yum remove openssl* rm -rf ***下载最新版的openssl文件 按照官网安装方法安装openssl 官方安装地址https://docs.python.org/3/using/unix.html#on-linu…...
【Spring Boot `@Autowired` Annotation】
文章目录 1. 使用Qualifier注解2. 使用Primary注解3. 手动注入(较少推荐) 在Spring Boot中,Autowired注解用于自动装配bean。默认情况下,它按照类型进行装配。当存在多个相同类型的bean时,就会出现以下错误:…...
03.axios数据提交和错误处理
一.axios常用请求方法和数据提交 1. 想要提交数据,先来了解什么是请求方法 请求方法是一些固定单词的英文,例如:GET,POST,PUT,DELETE,PATCH(这些都是http协议规定的)&am…...
无人机生态环境监测、图像处理与GIS数据分析
构建“天空地”一体化监测体系是新形势下生态、环境、水文、农业、林业、气象等资源环境领域的重大需求,无人机生态环境监测在一体化监测体系中扮演着极其重要的角色。通过无人机航空遥感技术可以实现对地表空间要素的立体观测,获取丰富多样的地理空间数…...
centos7.9升级ssh和openssl
一、环境 [roottmp179 package]# ssh -V OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017 [roottmp179 package]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) 二、 升级前准备 mkdir /opt/package cd /opt/package wget https://www.openssl.org/source…...
HttpURLConnection详解及使用
HttpURLConnection 请求响应流程 设置连接参数的方法 setAllowUserInteractionsetDoInputsetDoOutputsetIfModifiedSincesetUseCachessetDefaultAllowUserInteractionsetDefaultUseCaches 发送URL请求 建立实际连接之后,就是发送请求,把请求参数传到…...
npm下载时下载失败解决方法
1.清楚缓存 npm cache clean --force2.切换下载镜像 1.查看当前使用的镜像地址命令 npm config get registry切换为淘宝镜像命令(安装一些package容易报错) npm config set registry https://registry.npm.taobao.org或官方: npm config…...
Python实战:浅析Python输入输出理解数据交换的基本原理
在Python编程中,输入输出是数据交换的基础。本文将深入探讨Python中的输入输出功能,包括标准输入输出、文件输入输出、格式化输出等。我们将通过具体的代码示例来展示如何使用Python进行数据输入和输出,并理解其背后的工作原理。 1. 标准输入…...
MySQL--explain执行计划详解
什么是执行计划? SQL的执行计划,通俗来说就是SQL的执行情况,一条SQL语句扫描哪些表,那个子查询先执行,是否用到了索引等等,只有当我们知道了这些情况之后才知道,才可以更好的去优化SQL…...
【NERF】入门学习整理(一)
【NERF】入门学习整理 1. 【NERF】入门学习整理1.1 基础含义输入输出2.位置编码含义3.代码中实际网路结构4.Volume Render部分(64个采样点处理)5.Volume Render部分(64个采样点处理)【NERF】及其变种(二) 1. 【NERF】入门学习整理 1.1 基础含义输入输出 深度学习模型中…...
基于ZYNQ PS-SPI的Flash驱动开发
本文使用PS-SPI实现Flash读写,PS-SPI的基础资料参考Xilinx UG1085的文档说明,其基础使用方法是,配置SPI模式,控制TXFIFO/RXFIFO,ZYNQ的IP自动完成发送TXFIFO数据,接收数据到RXFIFO,FIFO深度为12…...
Linux Shell:local关键字
Linux Shell:local关键字 在 Bash 中,local 是一个用于声明局部变量的关键字。当在函数内部使用 local 声明变量时,该变量只能在函数内部使用,并且不会对函数外部的同名变量产生影响。这样可以确保在函数内部定义的变量不会意外地…...
如何开发python毕业设计
开发Python毕业设计需要以下步骤: 选择项目主题: 选择一个与你的兴趣和专业相关的主题。确保主题具有一定的挑战性,但又不至于过于复杂,以确保你能够在规定时间内完成项目。 制定项目计划: 制定一个清晰的项目计划&…...
D*算法超详解 (D星算法 / Dynamic A*算法/ Dstar算法)(死循环解决--跟其他资料不一样奥)
所需先验知识(没有先验知识可能会有大碍,了解的话会对D*的理解有帮助):A*算法/ Dijkstra算法 何为D*算法 Dijkstra算法是无启发的寻找图中两节点的最短连接路径的算法,A*算法则是在Dijkstra算法的基础上加入了启发函数…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
PostgreSQL——环境搭建
一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在࿰…...
【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...
ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]
报错信息:libc.so.6: cannot open shared object file: No such file or directory: #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…...
