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

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引用-借用机制还是有限制的&#xff0c;比如我们要在多次函数调用中修改参数、跨线程传递参数并发修改的场景&#xff0c;单纯使用引用-借用机制就不灵了&#xff08;这种场景和引用-借用设计思想是冲突的&#xff09;。这时需要借助rust提供的Rc、Arc、Cell、RefCell对机制…...

JVM的工作流程

目录 1.JVM 简介 2.JVM 执行流程 3. JVM 运行时数据区 3.1 堆&#xff08;线程共享&#xff09; 3.3 本地方法栈&#xff08;线程私有&#xff09; 3.4 程序计数器&#xff08;线程私有&#xff09; 3.5 方法区&#xff08;线程共享&#xff09; 4.JVM 类加载 ① 类…...

kibana配置 dashbord,做可视化展示

一、环境介绍 这里我使用的kibana版本为7.17版本。 语言选择为中文。 需要已经有es&#xff0c;已经有kibana&#xff0c;并且都能正常访问。 二、背景介绍 kibana的可视化界面&#xff0c;可以配置很多监控统计界面。非常方便&#xff0c;做数据的可视化展示。 这篇文章&…...

前后端分离项目Docker部署指南(下)

目录 前言&#xff1a; 一.安装nginx 创建目录 上传nginx.conf至/data/nginx/conf文件夹中 运行启动容器 上传静态资源文件 ​编辑 访问结果 前言&#xff1a; 在上一篇博客中&#xff0c;我们深入探讨了如何使用Docker部署一个前后端分离的项目中的后端部分。我们构建…...

算法->位运算

有关位运算的操作符 >> <<&|^~ 常见位运算操作 给定一个数&#xff0c;确定它的二进制中第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’ &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448…...

centos7中python3.10找不到openssl解决方案

如果有用其他方法安装了其他版本openssl&#xff0c;记得卸载其他的openssl&#xff0c;删除其他的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. 手动注入&#xff08;较少推荐&#xff09; 在Spring Boot中&#xff0c;Autowired注解用于自动装配bean。默认情况下&#xff0c;它按照类型进行装配。当存在多个相同类型的bean时&#xff0c;就会出现以下错误&#xff1a…...

03.axios数据提交和错误处理

一.axios常用请求方法和数据提交 1. 想要提交数据&#xff0c;先来了解什么是请求方法 请求方法是一些固定单词的英文&#xff0c;例如&#xff1a;GET&#xff0c;POST&#xff0c;PUT&#xff0c;DELETE&#xff0c;PATCH&#xff08;这些都是http协议规定的&#xff09;&am…...

无人机生态环境监测、图像处理与GIS数据分析

构建“天空地”一体化监测体系是新形势下生态、环境、水文、农业、林业、气象等资源环境领域的重大需求&#xff0c;无人机生态环境监测在一体化监测体系中扮演着极其重要的角色。通过无人机航空遥感技术可以实现对地表空间要素的立体观测&#xff0c;获取丰富多样的地理空间数…...

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请求 建立实际连接之后&#xff0c;就是发送请求&#xff0c;把请求参数传到…...

npm下载时下载失败解决方法

1.清楚缓存 npm cache clean --force2.切换下载镜像 1.查看当前使用的镜像地址命令 npm config get registry切换为淘宝镜像命令&#xff08;安装一些package容易报错&#xff09; npm config set registry https://registry.npm.taobao.org或官方&#xff1a; npm config…...

Python实战:浅析Python输入输出理解数据交换的基本原理

在Python编程中&#xff0c;输入输出是数据交换的基础。本文将深入探讨Python中的输入输出功能&#xff0c;包括标准输入输出、文件输入输出、格式化输出等。我们将通过具体的代码示例来展示如何使用Python进行数据输入和输出&#xff0c;并理解其背后的工作原理。 1. 标准输入…...

MySQL--explain执行计划详解

什么是执行计划&#xff1f; SQL的执行计划&#xff0c;通俗来说就是SQL的执行情况&#xff0c;一条SQL语句扫描哪些表&#xff0c;那个子查询先执行&#xff0c;是否用到了索引等等&#xff0c;只有当我们知道了这些情况之后才知道&#xff0c;才可以更好的去优化SQL&#xf…...

【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读写&#xff0c;PS-SPI的基础资料参考Xilinx UG1085的文档说明&#xff0c;其基础使用方法是&#xff0c;配置SPI模式&#xff0c;控制TXFIFO/RXFIFO&#xff0c;ZYNQ的IP自动完成发送TXFIFO数据&#xff0c;接收数据到RXFIFO&#xff0c;FIFO深度为12…...

Linux Shell:local关键字

Linux Shell&#xff1a;local关键字 在 Bash 中&#xff0c;local 是一个用于声明局部变量的关键字。当在函数内部使用 local 声明变量时&#xff0c;该变量只能在函数内部使用&#xff0c;并且不会对函数外部的同名变量产生影响。这样可以确保在函数内部定义的变量不会意外地…...

如何开发python毕业设计

开发Python毕业设计需要以下步骤&#xff1a; 选择项目主题&#xff1a; 选择一个与你的兴趣和专业相关的主题。确保主题具有一定的挑战性&#xff0c;但又不至于过于复杂&#xff0c;以确保你能够在规定时间内完成项目。 制定项目计划&#xff1a; 制定一个清晰的项目计划&…...

D*算法超详解 (D星算法 / Dynamic A*算法/ Dstar算法)(死循环解决--跟其他资料不一样奥)

所需先验知识&#xff08;没有先验知识可能会有大碍&#xff0c;了解的话会对D*的理解有帮助&#xff09;&#xff1a;A*算法/ Dijkstra算法 何为D*算法 Dijkstra算法是无启发的寻找图中两节点的最短连接路径的算法&#xff0c;A*算法则是在Dijkstra算法的基础上加入了启发函数…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

CTF show Web 红包题第六弹

提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框&#xff0c;很难让人不联想到SQL注入&#xff0c;但提示都说了不是SQL注入&#xff0c;所以就不往这方面想了 ​ 先查看一下网页源码&#xff0c;发现一段JavaScript代码&#xff0c;有一个关键类ctfs…...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

Linux nano命令的基本使用

参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时&#xff0c;显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

Docker拉取MySQL后数据库连接失败的解决方案

在使用Docker部署MySQL时&#xff0c;拉取并启动容器后&#xff0c;有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致&#xff0c;包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因&#xff0c;并提供解决方案。 一、确认MySQL容器的运行状态 …...

rm视觉学习1-自瞄部分

首先先感谢中南大学的开源&#xff0c;提供了很全面的思路&#xff0c;减少了很多基础性的开发研究 我看的阅读的是中南大学FYT战队开源视觉代码 链接&#xff1a;https://github.com/CSU-FYT-Vision/FYT2024_vision.git 1.框架&#xff1a; 代码框架结构&#xff1a;readme有…...

break 语句和 continue 语句

break语句和continue语句都具有跳转作用&#xff0c;可以让代码不按既有的顺序执行 break break语句用于跳出代码块或循环 1 2 3 4 5 6 for (var i 0; i < 5; i) { if (i 3){ break; } console.log(i); } continue continue语句用于立即终…...

RFID推动新能源汽车零部件生产系统管理应用案例

RFID推动新能源汽车零部件生产系统管理应用案例 一、项目背景 新能源汽车零部件场景 在新能源汽车零部件生产领域&#xff0c;电子冷却水泵等关键部件的装配溯源需求日益增长。传统 RFID 溯源方案采用 “网关 RFID 读写头” 模式&#xff0c;存在单点位单独头溯源、网关布线…...