Use tokio::sync::Mutex inside async functions and std::sync::Mutex inside synchronous code to prevent deadlocks. Using std::sync::Mutex in an async context blocks the entire runtime thread, halting all other tasks until the lock is released.
use tokio::sync::Mutex;
use std::sync::Arc;
async fn update_counter(counter: Arc<Mutex<i32>>) {
let mut num = counter.lock().await;
*num += 1;
}
If you must use std::sync::Mutex in async code, wrap the blocking operation in tokio::task::spawn_blocking to offload it to a separate thread pool.