typestar

Holding a lock across an await in Rust

tokio's Mutex may be held across an await point; the std one may not.

use std::sync::Arc;
use tokio::sync::Mutex;
use tokio::time::{sleep, Duration};

#[tokio::main]
async fn main() {
    let log = Arc::new(Mutex::new(Vec::new()));
    let mut tasks = Vec::new();

    for id in 0..3 {
        let log = Arc::clone(&log);
        tasks.push(tokio::spawn(async move {
            let mut entries = log.lock().await;
            sleep(Duration::from_millis(5)).await;
            entries.push(id);
        }));
    }

    for t in tasks {
        t.await.unwrap();
    }

    let mut entries = log.lock().await.clone();
    entries.sort();
    println!("{:?}", entries);
}

How it works

  1. An async lock yields instead of blocking the thread.
  2. Use the std Mutex when the critical section has no await.
  3. Arc still provides the shared ownership.

Keywords and builtins used here

The run, in numbers

Lines
26
Characters to type
496
Tokens
175
Three-star pace
110 tpm

At the three-star pace of 110 tokens a minute, this run takes about 95 seconds.

Type this snippet

Step 6 of 6 in Async with tokio, step 14 of 15 in Concurrency & async.

← Previous Next →