Yes, using Atomics in an async context is no problem.
Most of them are lock-free (=can't even block).
Even if you would block, it is still recommended to use normal, blocking synchronization primitives over async ones, unless you hold that lock during an await
.
For more info I quote the respective chapter of the tokio tutorial:
On using std::sync::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
.
Note that this is of course only true if all the threads accessing said lock/atomic are also async worker threads. If you have external threads that could block the mutex, you have to consider waiting for that mutex a blocking operation and treat it as such.