Skip to content

[All] Mutex performance improvement: asynchronous mutex vs synchronous mutex #119

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Tracked by #1
rainliu opened this issue Oct 19, 2021 · 4 comments
Open
Tracked by #1

Comments

@rainliu
Copy link
Member

rainliu commented Oct 19, 2021

tokio::sync::Mutex vs std::sync::Mutex vs parking_lot::Mutex

change tokio::sync::Mutex to std::sync::Mutex or parking_lot::Mutex when it is not across .await

@rainliu
Copy link
Member Author

rainliu commented Oct 19, 2021

For example, don't use std::sync::Mutex or parking_lot::Mutex on the following case, which hold the lock across the .await point.

async fn work(mtx: &Mutex<i32>) {
    println!("lock");
    {
        let mut v = mtx.lock().unwrap();
        println!("locked");
        // synchronous Mutex lock across .await point will cause deadlock,
        // for this case, use asynchronous Mutex
        delay_for(Duration::from_millis(100)).await;
        *v += 1;
    }
    println!("unlock")
}

@rainliu
Copy link
Member Author

rainliu commented Oct 19, 2021

it is ok to use std::sync::Mutex or parking_lot::Mutex when it is not across the .await point, for example:

async fn work(mtx: &Mutex<i32>) {
    println!("lock");
    {
        let mut v = mtx.lock().unwrap();
        println!("locked");        
        *v += 1;
    }
    println!("unlock")
}

This was referenced Oct 19, 2021
@rainliu rainliu changed the title [All] Mutex performance improvement [All] Mutex performance improvement: asynchronous mutex vs synchronous mutex Oct 19, 2021
@alexlapa
Copy link
Contributor

it is ok to use std::sync::Mutex or parking_lot::Mutex when it is not across the .await point, for example:

It also kinda depends on what thread is being locked. Locking runtime's (tokio/async-std) threads might result in whole system performance degradation, since locking runtime's threads would prevent them from driving other tasks (like i/o) or even disrupt the whole cooperative scheduling. Blocking operations are usually offloaded on a separate threads (spawn_blocking)

@k0nserv
Copy link
Member

k0nserv commented Nov 1, 2021

@alexlapa

Tokio's docs recommend using std::sync::Mutex or parking_lot::Mutex

Note, std::sync::Mutex and not tokio::sync::Mutex is used to guard the HashMap. A common error is to unconditionally use tokio::sync::Mutex from within async code. An async mutex is a mutex that is locked across calls to .await.

A synchronous mutex will block the current thread when waiting to acquire the lock. This, in turn, will block other tasks from processing. However, switching to tokio::sync::Mutex usually does not help as the asynchronous mutex uses a synchronous mutex internally.

As a rule of thumb, using a synchronous mutex from within asynchronous code is fine as long as contention remains low and the lock is not held across calls to .await. Additionally, consider using parking_lot::Mutex as a faster alternative to std::sync::Mutex.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants