Is there a way to use atomic types in an asynchronous context instead of an asynchronous Mutex
or RwLock
? Can standard atomics be used as is in an asynchronous context?
Or, for example, is there an asynchronous equivalent of std::sync::atomic::AtomicUsize
with load
/ store
methods, which could replace something like tokio::sync::RwLock<usize>
with read().await
/ write().await
methods?
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 nottokio::sync::Mutex
is used to guard theHashMap
. A common error is to unconditionally usetokio::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 usingparking_lot::Mutex
as a faster alternative tostd::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.