@@ -107,6 +107,67 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult};
107
107
///
108
108
/// *guard += 1;
109
109
/// ```
110
+ ///
111
+ /// It is sometimes a good idea (or even necessary) to manually drop the mutex
112
+ /// to unlock it as soon as possible. If you need the resource until the end of
113
+ /// the scope, this is not needed.
114
+ ///
115
+ /// ```
116
+ /// use std::sync::{Arc, Mutex};
117
+ /// use std::thread;
118
+ ///
119
+ /// const N: usize = 3;
120
+ ///
121
+ /// // Some data to work with in multiple threads.
122
+ /// let data_mutex = Arc::new(Mutex::new([1, 2, 3, 4]));
123
+ /// // The result of all the work across all threads.
124
+ /// let res_mutex = Arc::new(Mutex::new(0));
125
+ ///
126
+ /// // Threads other than the main thread.
127
+ /// let mut threads = Vec::with_capacity(N);
128
+ /// (0..N).for_each(|_| {
129
+ /// // Getting clones for the mutexes.
130
+ /// let data_mutex_clone = Arc::clone(&data_mutex);
131
+ /// let res_mutex_clone = Arc::clone(&res_mutex);
132
+ ///
133
+ /// threads.push(thread::spawn(move || {
134
+ /// let data = *data_mutex_clone.lock().unwrap();
135
+ /// // This is the result of some important and long-ish work.
136
+ /// let result = data.iter().fold(0, |acc, x| acc + x * 2);
137
+ /// // We drop the `data` explicitely because it's not necessary anymore
138
+ /// // and the thread still has work to do. This allow other threads to
139
+ /// // start working on the data immediately, without waiting
140
+ /// // for the rest of the unrelated work to be done here.
141
+ /// std::mem::drop(data);
142
+ /// *res_mutex_clone.lock().unwrap() += result;
143
+ /// }));
144
+ /// });
145
+ ///
146
+ /// let data = *data_mutex.lock().unwrap();
147
+ /// // This is the result of some important and long-ish work.
148
+ /// let result = data.iter().fold(0, |acc, x| acc + x * 2);
149
+ /// // We drop the `data` explicitely because it's not necessary anymore
150
+ /// // and the thread still has work to do. This allow other threads to
151
+ /// // start working on the data immediately, without waiting
152
+ /// // for the rest of the unrelated work to be done here.
153
+ /// //
154
+ /// // It's even more important here because we `.join` the threads after that.
155
+ /// // If we had not dropped the lock, a thread could be waiting forever for
156
+ /// // it, causing a deadlock.
157
+ /// std::mem::drop(data);
158
+ /// // Here the lock is not assigned to a variable and so, even if the scope
159
+ /// // does not end after this line, the mutex is still released:
160
+ /// // there is no deadlock.
161
+ /// *res_mutex.lock().unwrap() += result;
162
+ ///
163
+ /// threads.into_iter().for_each(|thread| {
164
+ /// thread
165
+ /// .join()
166
+ /// .expect("The thread creating or execution failed !")
167
+ /// });
168
+ ///
169
+ /// assert_eq!(*res_mutex.lock().unwrap(), 80);
170
+ /// ```
110
171
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
111
172
#[ cfg_attr( not( test) , rustc_diagnostic_item = "mutex_type" ) ]
112
173
pub struct Mutex < T : ?Sized > {
0 commit comments