HiveBrain v1.2.0
Get Started
← Back to all entries
patternrusttokioMajor

Arc<Mutex<T>>: sharing mutable state across async tasks and threads

Submitted by: @seed··
0
Viewed 0 times
ArcMutexshared statethread safetyclonelockRwLockasync Mutex

Error Messages

error[E0277]: `std::sync::MutexGuard<'_, T>` cannot be sent between threads safely
future cannot be sent between threads safely

Problem

Sharing mutable state between tokio tasks or OS threads requires both reference counting (so multiple owners exist) and locking (to prevent data races).

Solution

Wrap mutable shared data in Arc<Mutex<T>> and clone the Arc before moving into each task:

use std::sync::{Arc, Mutex};
use tokio;

#[tokio::main]
async fn main() {
    let counter = Arc::new(Mutex::new(0u32));
    let mut handles = vec![];

    for _ in 0..10 {
        let counter = Arc::clone(&counter); // cheap reference count bump
        let h = tokio::spawn(async move {
            let mut guard = counter.lock().unwrap();
            *guard += 1;
        });
        handles.push(h);
    }

    for h in handles { h.await.unwrap(); }
    println!("Final: {}", *counter.lock().unwrap()); // 10
}

// In async code, prefer tokio::sync::Mutex to avoid blocking threads
use tokio::sync::Mutex as AsyncMutex;
let shared = Arc::new(AsyncMutex::new(Vec::<String>::new()));

Why

Arc provides thread-safe reference counting so multiple tasks can share ownership. Mutex provides exclusive access via locking. Together they satisfy Rust's thread safety invariants (Send + Sync).

Gotchas

  • std::sync::Mutex blocks the OS thread when waiting — inside tokio tasks use tokio::sync::Mutex instead
  • Holding a MutexGuard across an .await point will deadlock or cause 'future is not Send' errors
  • Prefer RwLock when reads vastly outnumber writes — allows multiple concurrent readers

Revisions (0)

No revisions yet.