How to Prevent File Write Chaos in Rust with Tokio Mutex

This article demonstrates the problem of unordered file content when multiple Tokio tasks write concurrently in Rust, shows a sample program that exhibits the issue, and provides a solution using Tokio’s asynchronous Mutex to synchronize file access, ensuring ordered and complete writes.

JD Cloud Developers
JD Cloud Developers
JD Cloud Developers
How to Prevent File Write Chaos in Rust with Tokio Mutex

When writing to a file from many concurrent Tokio tasks in Rust, the output can become unordered because the write operations are not synchronized.

The following example creates 200 parallel tasks that each write a timestamp and an index to /tmp/parallel without any mutual‑exclusion mechanism, resulting in interleaved and out‑of‑order lines.

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;
            }
            // No write mutex here
            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();
    }
}

The produced file shows repeated timestamps with irregular ordering, confirming the lack of synchronization.

To fix the problem we wrap the file in an Arc<Mutex<File>> and acquire the lock before each write.

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("
".as_bytes()).unwrap();
        f.write_all("
".as_bytes()).unwrap();
    }
}

With the mutex each write is performed atomically, producing a file where every line appears in the correct order and each write completes fully.

The full source code is available at the provided GitHub repository.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

RustTokiomutexFile I/O
JD Cloud Developers
Written by

JD Cloud Developers

JD Cloud Developers (Developer of JD Technology) is a JD Technology Group platform offering technical sharing and communication for AI, cloud computing, IoT and related developers. It publishes JD product technical information, industry content, and tech event news. Embrace technology and partner with developers to envision the future.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.