@@ -10,23 +10,28 @@ use std::sync::Arc;
10
10
11
11
/// An asynchronous `Mutex`-like type.
12
12
///
13
- /// This type acts similarly to an asynchronous [`std::sync::Mutex`], with one
14
- /// major difference : [`lock`] does not block and the lock guard can be held
15
- /// across await points.
13
+ /// This type acts similarly to [`std::sync::Mutex`], with two major
14
+ /// differences : [`lock`] is an async method so does not block, and the lock
15
+ /// guard is designed to be held across `. await` points.
16
16
///
17
17
/// # Which kind of mutex should you use?
18
18
///
19
19
/// Contrary to popular belief, it is ok and often preferred to use the ordinary
20
- /// [`Mutex`][std] from the standard library in asynchronous code. This section
21
- /// will help you decide on which kind of mutex you should use.
20
+ /// [`Mutex`][std] from the standard library in asynchronous code.
22
21
///
23
- /// The primary use case of the async mutex is to provide shared mutable access
24
- /// to IO resources such as a database connection. If the data stored behind the
25
- /// mutex is just data, it is often better to use a blocking mutex such as the
26
- /// one in the standard library or [`parking_lot`]. This is because the feature
27
- /// that the async mutex offers over the blocking mutex is that it is possible
28
- /// to keep the mutex locked across an `.await` point, which is rarely necessary
29
- /// for data.
22
+ /// The feature that the async mutex offers over the blocking mutex is the
23
+ /// ability to keep it locked across an `.await` point. This makes the async
24
+ /// mutex more expensive than the blocking mutex, so the blocking mutex should
25
+ /// be preferred in the cases where it can be used. The primary use case for the
26
+ /// async mutex is to provide shared mutable access to IO resources such as a
27
+ /// database connection. If the value behind the mutex is just data, it's
28
+ /// usually appropriate to use a blocking mutex such as the one in the standard
29
+ /// library or [`parking_lot`].
30
+ ///
31
+ /// Note that, although the compiler will not prevent the std `Mutex` from holding
32
+ /// its guard across `.await` points in situations where the task is not movable
33
+ /// between threads, this virtually never leads to correct concurrent code in
34
+ /// practice as it can easily lead to deadlocks.
30
35
///
31
36
/// A common pattern is to wrap the `Arc<Mutex<...>>` in a struct that provides
32
37
/// non-async methods for performing operations on the data within, and only
@@ -123,7 +128,8 @@ pub struct Mutex<T: ?Sized> {
123
128
c : UnsafeCell < T > ,
124
129
}
125
130
126
- /// A handle to a held `Mutex`.
131
+ /// A handle to a held `Mutex`. The guard can be held across any `.await` point
132
+ /// as it is [`Send`].
127
133
///
128
134
/// As long as you have this guard, you have exclusive access to the underlying
129
135
/// `T`. The guard internally borrows the `Mutex`, so the mutex will not be
0 commit comments