sync: improve doc on blocking mutex (#3645)

This commit is contained in:
CorinJG
2021-03-27 13:26:10 +01:00
committed by GitHub
parent 7384813979
commit 1a80d6eee5
+19 -13
View File
@@ -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<Mutex<...>>` in a struct that provides
/// non-async methods for performing operations on the data within, and only
@@ -123,7 +128,8 @@ pub struct Mutex<T: ?Sized> {
c: UnsafeCell<T>,
}
/// 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