You need a mutex when you want to modify some value from multiple independently spawned tasks. If the code compiles without a mutex, then it should be good unless you break something with unsafe code. You should generally use the standard library mutex if the duration of any lock is very short and never held across an .await
, and the async mutex if you sometimes need to hold it for a long time, or if the lock is ever held across an .await
.
Check out the documentation for Tokio's mutex:
There are some situations where you should prefer the mutex from the standard library. Generally this is the case if:
- The lock does not need to be held across await points.
- The duration of any single lock is near-instant.
On the other hand, the Tokio mutex is for the situation where the lock needs to be held for longer periods of time, or across await points.
This should apply equally for all asynchronous mutexes.
There might not be an RwLock
in the futures crate, but both Tokio and async-std provide one. You can find the doc for Tokio's here.
Unlike mutexes, I recommend using asynchronous rw-locks for all asynchronous applications, because even if each individual lock is held for only a very short time, many read locks might keep a write lock for a long time, which is not a good idea. The std RwLock
documentation says this:
The priority policy of the lock is dependent on the underlying operating system's implementation, and this type does not guarantee that any particular policy will be used.
If the priority was write-preferring, my opinion on this would be different. Note that Tokio's mutex uses this priority:
The priority policy of Tokio's read-write lock is fair (or write-preferring), in order to ensure that readers cannot starve writers. Fairness is ensured using a first-in, first-out queue for the tasks awaiting the lock; if a task that wishes to acquire the write lock is at the head of the queue, read locks will not be given out until the write lock has been released. This is in contrast to the Rust standard library's
std::sync::RwLock
, where the priority policy is dependent on the operating system's implementation.
As far as I know, the async-std RwLock
does not guarantee a fair priority, but it is still better than the standard library's lock, as the thread is not blocked while the task waits for the lock.