Skip to content

Commit 1a80d6e

Browse files
authoredMar 27, 2021
sync: improve doc on blocking mutex (#3645)
1 parent 7384813 commit 1a80d6e

File tree

1 file changed

+19
-13
lines changed

1 file changed

+19
-13
lines changed
 

‎tokio/src/sync/mutex.rs

+19-13
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,28 @@ use std::sync::Arc;
1010

1111
/// An asynchronous `Mutex`-like type.
1212
///
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.
1616
///
1717
/// # Which kind of mutex should you use?
1818
///
1919
/// 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.
2221
///
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.
3035
///
3136
/// A common pattern is to wrap the `Arc<Mutex<...>>` in a struct that provides
3237
/// non-async methods for performing operations on the data within, and only
@@ -123,7 +128,8 @@ pub struct Mutex<T: ?Sized> {
123128
c: UnsafeCell<T>,
124129
}
125130

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`].
127133
///
128134
/// As long as you have this guard, you have exclusive access to the underlying
129135
/// `T`. The guard internally borrows the `Mutex`, so the mutex will not be

0 commit comments

Comments
 (0)
Please sign in to comment.