diff --git a/tokio/src/sync/mutex.rs b/tokio/src/sync/mutex.rs index 2e97eb8f127..0a118e7f824 100644 --- a/tokio/src/sync/mutex.rs +++ b/tokio/src/sync/mutex.rs @@ -10,23 +10,28 @@ use std::sync::Arc; /// An asynchronous `Mutex`-like type. /// -/// This type acts similarly to an asynchronous [`std::sync::Mutex`], with one -/// major difference: [`lock`] does not block and the lock guard can be held -/// across await points. +/// This type acts similarly to [`std::sync::Mutex`], with two major +/// differences: [`lock`] is an async method so does not block, and the lock +/// guard is designed to be held across `.await` points. /// /// # Which kind of mutex should you use? /// /// Contrary to popular belief, it is ok and often preferred to use the ordinary -/// [`Mutex`][std] from the standard library in asynchronous code. This section -/// will help you decide on which kind of mutex you should use. +/// [`Mutex`][std] from the standard library in asynchronous code. /// -/// The primary use case of the async mutex is to provide shared mutable access -/// to IO resources such as a database connection. If the data stored behind the -/// mutex is just data, it is often better to use a blocking mutex such as the -/// one in the standard library or [`parking_lot`]. This is because the feature -/// that the async mutex offers over the blocking mutex is that it is possible -/// to keep the mutex locked across an `.await` point, which is rarely necessary -/// for data. +/// The feature that the async mutex offers over the blocking mutex is the +/// ability to keep it locked across an `.await` point. This makes the async +/// mutex more expensive than the blocking mutex, so the blocking mutex should +/// be preferred in the cases where it can be used. The primary use case for the +/// async mutex is to provide shared mutable access to IO resources such as a +/// database connection. If the value behind the mutex is just data, it's +/// usually appropriate to use a blocking mutex such as the one in the standard +/// library or [`parking_lot`]. +/// +/// Note that, although the compiler will not prevent the std `Mutex` from holding +/// its guard across `.await` points in situations where the task is not movable +/// between threads, this virtually never leads to correct concurrent code in +/// practice as it can easily lead to deadlocks. /// /// A common pattern is to wrap the `Arc>` in a struct that provides /// non-async methods for performing operations on the data within, and only @@ -123,7 +128,8 @@ pub struct Mutex { c: UnsafeCell, } -/// A handle to a held `Mutex`. +/// A handle to a held `Mutex`. The guard can be held across any `.await` point +/// as it is [`Send`]. /// /// As long as you have this guard, you have exclusive access to the underlying /// `T`. The guard internally borrows the `Mutex`, so the mutex will not be