在實際開發(fā)過程中,我們可能會遇到并發(fā)寫文件的場景,如果處理不當很可能出現(xiàn)文件內(nèi)容亂序問題。下面我們通過一個示例程序描述這一過程并給出解決該問題的方法。
use std::{
fs::{self, File, OpenOptions},
io::{Write},
sync::Arc,
time::{SystemTime, UNIX_EPOCH},
};
use tokio::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::new().unwrap();
rt.block_on(async {
loop {
while set.len() >= max_tasks {
set.join_next().await;
}
未做寫互斥函數(shù)
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("
".as_bytes()).unwrap();
file.write_all("
".as_bytes()).unwrap();
}
}
代碼不復雜,tokio 實現(xiàn)一個并發(fā)runtime,寫文件函數(shù)是直接寫時間戳,為了方便展示亂序所以寫入兩次換行。
輸出的文本大概長這樣:
1691287258_979 1691287258_7931691287258_301 1691287258_7431691287258_603 1691287258_8941691287258_47 1691287258_895 1691287258_553 1691287258_950 1691287258_980 1691287258_48 1691287258_302 1691287258_896 1691287258_744 1691287258_6041691287258_554
很明顯,寫入并未達到預期,間隔并不平均,函數(shù)內(nèi)部的執(zhí)行步驟是亂序的。
我們把上面的程序改造一下:
use std::{
fs::{self, File, OpenOptions},
io::Write,
sync::Arc,
time::{SystemTime, UNIX_EPOCH},
};
use tokio::Mutex;
use tokio::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::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>) {
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("
".as_bytes()).unwrap();
f.write_all("
".as_bytes()).unwrap();
}
}
這次我們用到了tokio::Mutex,write_line_mutex函數(shù)在每次執(zhí)行寫任務以前先獲取文件互斥鎖。
看看這次的文件內(nèi)容:
1691288040_374 1691288040_374 1691288040_374 1691288040_375 1691288040_374 1691288040_374 1691288040_374 1691288040_374 1691288040_374 1691288040_374 1691288040_374 1691288040_374 1691288040_374 1691288040_374 1691288040_375 1691288040_375 1691288040_374 1691288040_375 1691288040_375 1691288040_375 1691288040_375 1691288040_375 1691288040_375 1691288040_375 1691288040_375 1691288040_375 1691288040_375
寫入的格式正確,保證每次函數(shù)寫函數(shù)完整執(zhí)行。
關于文件寫互斥這點事兒,今兒就聊到這。
審核編輯:劉清
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。
舉報投訴
-
Unix系統(tǒng)
+關注
關注
0文章
15瀏覽量
9931 -
ARC
+關注
關注
0文章
50瀏覽量
17135 -
rust語言
+關注
關注
0文章
57瀏覽量
3262
原文標題:文盤Rust -- Mutex解決并發(fā)寫文件亂序問題
文章出處:【微信號:Rust語言中文社區(qū),微信公眾號:Rust語言中文社區(qū)】歡迎添加關注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關推薦
熱點推薦
詳解linux內(nèi)核中的mutex同步機制
在linux內(nèi)核中,互斥量(mutex,即mutual exclusion)是一種保證串行化的睡眠鎖機制。和spinlock的語義類似,都是允許一個執(zhí)行線索進入臨界區(qū),不同的是當無法獲得鎖的時候
Linux內(nèi)核同步機制mutex詳解
在linux內(nèi)核中,互斥量mutex是一種保證CPU串行運行的睡眠鎖機制。和spinlock類似,都是同一個時刻只有一個線程進入臨界資源,不同的是,當無法獲取鎖的時候,spinlock原地自旋,而mutex則是選擇掛起當前線程,進入阻塞狀態(tài)。所以,
發(fā)表于 06-26 16:05
?1935次閱讀
Raw-os mutex 篇
1mutex 支持FIFO 和PRIO 的任務阻塞策略,如果是FIFO 的話阻塞隊列的順序是按照先來后到的次序去排列阻塞任務,PRIO 策略的話是按照優(yōu)先級的排序。具體的設置可以直接設置這個結(jié)構(gòu)體中
發(fā)表于 02-27 14:03
關于mutex 鎖
mutex的出現(xiàn)是為了解決優(yōu)先級反轉(zhuǎn)的問題,由于優(yōu)先級反轉(zhuǎn)對實時性影響太大,所以mutex 的穩(wěn)定性直接影響了實時性。縱觀目前多種實時操作系統(tǒng)mutex 的設計原理是多多少少有一點問題的,raw
發(fā)表于 02-27 14:34
labview寫入access數(shù)據(jù)庫亂序問題
用database insert 插入數(shù)據(jù),移位寄存器當作順序編號,發(fā)現(xiàn)不管循環(huán)框頻率設多少,到編號713這里必定會跳到737,然后中間這段會在1035后出現(xiàn),其他地方也有類似的亂序,多次寫入亂序
發(fā)表于 08-09 10:23
STM32G473是如何利用DMA接收并發(fā)送數(shù)據(jù)的
STM32G473是如何利用DMA接收并發(fā)送數(shù)據(jù)的?其實現(xiàn)方法是什么?
發(fā)表于 12-08 07:18
互斥量Mutex相關資料推薦
這里寫目錄標題概述API二級目錄三級目錄概述APItx_mutex_createtx_mutex_deletetx_mutex_gettx_mutex_put二級目錄三級目錄
發(fā)表于 02-22 07:40
適用于IPTV大并發(fā)應用的文件格式
分析交互式網(wǎng)絡電視(IPTV)大并發(fā)應用的特性,提出一種適用于IPTV大并發(fā)應用的服務器內(nèi)部文件格式cl4文件格式。該文件格式采用了符合IP
發(fā)表于 04-15 10:02
?17次下載
什么是CPU分枝/亂序執(zhí)行?
什么是分枝/亂序執(zhí)行?
分枝(branch)是指程序運行時需要改變的節(jié)點。分枝有無條件分枝和有條件分枝,其中無條件分枝只
發(fā)表于 02-04 10:49
?1081次閱讀
Linux多線程同步互斥量Mutex詳解
pthread_mutex_destroy(pthread_mutex_t *mutex);頭文件:返回值: 成功則返回0, 出錯則返回錯誤編號.說明: 如果使用默認的屬性初始化互斥
發(fā)表于 04-02 14:45
?490次閱讀
ThreadX(七)------互斥量Mutex
這里寫目錄標題概述API二級目錄三級目錄概述APItx_mutex_createtx_mutex_deletetx_mutex_gettx_mutex_put二級目錄三級目錄
發(fā)表于 12-28 19:29
?8次下載
編譯器的亂序策略
寫這篇文章的目的,是想明確下cpu指令亂序這件事。只要是熟悉計算機底層系統(tǒng)的同學就會知道,程序里面的每行代碼的執(zhí)行順序,有可能會被編譯器和cpu根據(jù)某種策略,給打亂掉,目的是為了性能的提升,讓指令的執(zhí)行能夠盡可能的并行起來。
亂序文件如何重新命名編號
如下圖所示,在本地文件夾中有這樣一堆視頻文件,在這種情況下并不是亂序的。 但是將其上傳到網(wǎng)盤中后,就會經(jīng)常變成亂序。即它們會按照1、10、11、2、20這樣排序,并不方便我們按順序去依
MQ消息亂序問題解析與實戰(zhàn)解決方案
詳細探討MQ消息亂序問題的根源,并提供一系列在實際應用中可行的解決方案。 2. MQ消息亂序問題分析 常見的MQ消息亂序問題的根源主要可以歸結(jié)為以下幾點: 2.1 相同topic內(nèi)的消息亂序
如何利用Mutex解決并發(fā)寫文件亂序的問題?
評論