文盘Rust -- Mutex解决并发写文件乱序问题 | 京东云技术团队
在实际开发过程中,我们可能会遇到并发写文件的场景,如果处理不当很可能出现文件内容乱序问题。下面我们通过一个示例程序描述这一过程并给出解决该问题的方法。
use std::{fs::{self, File, OpenOptions},io::{Write},sync::Arc,time::{SystemTime, UNIX_EPOCH},
};
use tokio::task::JoinSet;fn main() {println!("parallel write file!");let max_tasks = 200;let _ = fs::remove_file("/tmp/parallel");let file_ref = OpenOptions::new().create(true).write(true).append(true).open("/tmp/parallel").unwrap();let mut set: JoinSet<()> = JoinSet::new();let rt = tokio::runtime::Runtime::new().unwrap();rt.block_on(async {loop {while set.len() >= max_tasks {set.join_next().await;}未做写互斥函数let mut file_ref = OpenOptions::new().create(true).write(true).append(true).open("/tmp/parallel").unwrap();set.spawn(async move { write_line(&mut file_ref) });}});
}fn write_line(file: &mut File) {for i in 0..1000 {let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();let mut content = now.as_secs().to_string();content.push_str("_");content.push_str(&i.to_string());file.write_all(content.as_bytes()).unwrap();file.write_all("\n".as_bytes()).unwrap();file.write_all("\n".as_bytes()).unwrap();}
}
代码不复杂,tokio 实现一个并发runtime,写文件函数是直接写时间戳,为了方便展示乱序所以写入两次换行。
输出的文本大概长这样
1691287258_9791691287258_7931691287258_3011691287258_7431691287258_6031691287258_8941691287258_471691287258_895
1691287258_5531691287258_950
1691287258_9801691287258_48
1691287258_3021691287258_896
1691287258_7441691287258_6041691287258_554
很明显,写入并未达到预期,间隔并不平均,函数内部的执行步骤是乱序的。
我们把上面的程序改造一下
use std::{fs::{self, File, OpenOptions},io::Write,sync::Arc,time::{SystemTime, UNIX_EPOCH},
};
use tokio::sync::Mutex;
use tokio::task::JoinSet;fn main() {println!("parallel write file!");let max_tasks = 200;let _ = fs::remove_file("/tmp/parallel");let file_ref = OpenOptions::new().create(true).write(true).append(true).open("/tmp/parallel").unwrap();let f = Arc::new(Mutex::new(file_ref));let mut set: JoinSet<()> = JoinSet::new();let rt = tokio::runtime::Runtime::new().unwrap();rt.block_on(async {loop {while set.len() >= max_tasks {set.join_next().await;}let mut file = Arc::clone(&f);set.spawn(async move { write_line_mutex(&mut file).await });}});
}async fn write_line_mutex(mutex_file: &Arc<Mutex<File>>) {for i in 0..1000 {let mut f = mutex_file.lock().await;let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();let mut content = now.as_secs().to_string();content.push_str("_");content.push_str(&i.to_string());f.write_all(content.as_bytes()).unwrap();f.write_all("\n".as_bytes()).unwrap();f.write_all("\n".as_bytes()).unwrap();}
}
这次我们用到了tokio::sync::Mutex,write_line_mutex函数在每次执行写任务以前先获取文件互斥锁。
看看这次的文件内容
1691288040_3741691288040_3741691288040_3741691288040_3751691288040_3741691288040_3741691288040_3741691288040_3741691288040_3741691288040_3741691288040_3741691288040_3741691288040_3741691288040_3741691288040_3751691288040_3751691288040_3741691288040_3751691288040_3751691288040_3751691288040_3751691288040_3751691288040_3751691288040_3751691288040_3751691288040_3751691288040_375
写入的格式正确,保证每次函数写函数完整执行。
关于文件写互斥这点事儿,今儿就聊到这。
完整源码
作者:京东科技 贾世闻
来源:京东云开发者社区
相关文章:
文盘Rust -- Mutex解决并发写文件乱序问题 | 京东云技术团队
在实际开发过程中,我们可能会遇到并发写文件的场景,如果处理不当很可能出现文件内容乱序问题。下面我们通过一个示例程序描述这一过程并给出解决该问题的方法。 use std::{fs::{self, File, OpenOptions},io::{Write},sync::Arc,time::{SystemTime, UNI…...
数据结构算法--2 冒泡排序,选择排序,插入排序
基础排序算法 冒泡排序 思想就是将相邻元素两两比较,当一个元素大于右侧相邻元素时,交换他们的位置,小于右侧元素时,位置不变,最终序列中的最大元素,像气泡一样,到了最右侧。 这时冒泡排序第一…...
秋招面经——快手
Mysql mysql事务 共享锁与排他锁 共享锁:允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。(读都允许读,但我在读不允许你去改) 排他锁:允许一个事务去读一行,阻止其他事务获得相同…...
【STM32RT-Thread零基础入门】 2. 新建RT-Thread项目
硬件:STM32F103ZET6、ST-LINK、usb转串口工具 文章目录 前言一、新建RT-Thread项目二、项目结构三、构建项目四、下载程序(调试器下载)五、终端交互总结 前言 RT-Thread的全称是Real Time Thread,顾名思义,它是一个嵌…...
别人直播的时候怎么录屏?分享一些录屏方法
随着互联网的快速发展,直播已经成为人们日常生活中不可或缺的一部分。但是,有时候我们可能会错过某些重要的直播内容,这时候就需要录屏来保存和观看。那么,如何录屏别人的直播呢?本文将分享一些录屏方法和技巧&#…...
React Native 在高IOS版本下无法显示图片的问题处理
图片在低ios版本下可以看到图片,在高版本ios下显示不了图片 直接上解决方法 找文件 /node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m 修改源码 原代码 if (_currentFrame) {layer.contentsScale self.animatedImageScale;layer.contents…...
SSH远程连接MacOS catalina并进行终端颜色配置
一、开关SSH服务 在虚拟机上安装了MacOS catalina,想要使用SSH远程进行连接,但是使用“系统偏好设置”/“共享”/“远程登录”开关进行打开,却一直是正在启动“远程登录”: 难道是catalina有BUG?不过还是有方法的&…...
用JSON.toJSONString转JSON时,属性的值为null时,输出的JSON里没有该属性
1、问题 用JSON.toJSONString转JSON时,当属性值为null的话,转出来的JSON里没有了值为null的属性,属性丢失了 2、原因 用fastjson将java对象转json字符串时会默认去除空字段 2、解决办法 在JSON.toJSONString方法加上SerializerFeature这一…...
Java版企业电子招标采购系统源码—企业战略布局下的采购寻源tbms
项目说明 随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以…...
轻拍牛头(约数)
题意:求ai在n个数中,ai可以整除的数有多少个,不包括ai自己。 分析:暴力写需要n^2的时间复杂度,此时想一下预处理每个数的倍数,约数和倍数是有关系的,把每个数的倍数都加上1. #include<bits…...
Vc - Qt - 绘制窗口背景色
要在Qt中绘制一个背景颜色,你可以使用Qt的绘图功能来完成。下面是一种简单的方法: 步骤1:在你想要绘制背景颜色的QWidget(例如QMainWindow或QDialog)的派生类中,重写 它的paintEvent函数。步骤2:…...
js和cocos creator学习笔记
1.Javascript有哪些数据类型?举例两个最常见的内置对象数据类型? 常用的数据类型:Number,String,Boolean,Null,Undefined,Object 常见内置对象:Array,Function2.下面代码输出内容是什么? let a []; a[10] 10; console.log(a.length); console.log(a[0]); a[200] undefi…...
Ceph分布式存储系统
Ceph 是一个开源的分布式存储系统,旨在提供高性能、高可靠性和可扩展性的存储解决方案。它被设计用于管理大规模的数据,可以轻松地扩展到数千台服务器和多个存储节点,适用于私有云、公有云、虚拟化环境等多种场景。 Ceph 的主要特点和组件包…...
阿里云SMS,APi接口返回错误码
API错误码 更新时间:2023-06-29 16:33提交缺陷 产品详情 相关技术圈 我的收藏 调用API接口失败时,会返回错误码。本文档为您提供API接口错误码列表,请根据错误码和对应错误信息排查问题。 错误码(Code) 错误信息…...
Floyd算法
正如我们所知道的,Floyd算法用于求最短路径。Floyd算法可以说是Warshall算法的扩展,三个for循环就可以解决问题,所以它的时间复杂度为O(n^3)。 Floyd算法的基本思想如下:从任意节点A到任意节点B的最短路径不外乎2种可能ÿ…...
SpringBoot究竟应该如何学习?
如果你有Spring的基础,学习Spring Boot就很简单了。 首先要知道Spring Boot是建立在Spring框架之上的,它旨在简化和加速Java应用程序的开发过程。 Spring Boot的目标是简化Spring应用程序的配置和开发,通过提供自动配置、快速开发和零配置的…...
为什么很多人认为ChatGPT最好的替代工具是Claude?
ChatGPT引领着生成式AI聊天机器人领域,但Claude AI看起来是一个有力的竞争者。 前段时间,ChatGPT的强劲竞争对手Claude2面世。当时很多人认为它可能会取代ChatGPT,在体验过一段时间之后,深以为然。原因如下: 更强大的…...
学习Vue:简介和优势
什么是 Vue.js? Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架。它专注于视图层,并且可以轻松地集成到现有的项目中。Vue.js 的设计理念是渐进式,这意味着您可以根据项目的需要逐步引入 Vue.js,从而更好地控制应用的复…...
***is not a commit and a branch ‘***‘ cannot be created from it 报错
git执行如下代码 git checkout -b daily/1.0.0 origin/daily/1.0.0遇到报错 fatal: ‘origin/daily/1.0.27’ is not a commit and a branch ‘daily/1.0.27’ cannot be created from it 解决办法: git fetch --all原因: 报错说is not a commit而不是说branch doesn’t exis…...
QT信号槽连接方式
1.QT信号槽主要分两个连接方式,手动和自动: 1.1 使用 connect() 函数手动连接信号和槽: QObject::connect(sender, SIGNAL(signal()), receiver, SLOT(slot())); 自动: 1.2 使用 lambda 表达式连接信号和槽: connect(s…...
铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
