Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions src/libstd/sync/mutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,69 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult};
///
/// *guard += 1;
/// ```
///
/// It is sometimes a good idea (or even necessary) to manually drop the mutex
Comment thread
poliorcetics marked this conversation as resolved.
Outdated
/// to unlock it as soon as possible. If you need the resource until the end of
Comment thread
poliorcetics marked this conversation as resolved.
Outdated
/// the scope, this is not needed.
Comment thread
poliorcetics marked this conversation as resolved.
Outdated
///
/// ```
/// use std::sync::{Arc, Mutex};
Comment thread
poliorcetics marked this conversation as resolved.
/// use std::thread;
///
/// const N: usize = 3;
///
/// // Some data to work with in multiple threads.
/// let data_mutex = Arc::new(Mutex::new(vec![1, 2, 3, 4]));
/// // The result of all the work across all threads.
/// let res_mutex = Arc::new(Mutex::new(0));
///
/// // Threads other than the main thread.
/// let mut threads = Vec::with_capacity(N);
/// (0..N).for_each(|_| {
/// // Getting clones for the mutexes.
/// let data_mutex_clone = Arc::clone(&data_mutex);
/// let res_mutex_clone = Arc::clone(&res_mutex);
///
/// threads.push(thread::spawn(move || {
/// let mut data = data_mutex_clone.lock().unwrap();
/// // This is the result of some important and long-ish work.
/// let result = data.iter().fold(0, |acc, x| acc + x * 2);
/// data.push(result);
/// // We drop the `data` explicitely because it's not necessary anymore
/// // and the thread still has work to do. This allow other threads to
/// // start working on the data immediately, without waiting
/// // for the rest of the unrelated work to be done here.
/// std::mem::drop(data);
Comment thread
poliorcetics marked this conversation as resolved.
Outdated
/// *res_mutex_clone.lock().unwrap() += result;
/// }));
/// });
///
/// let mut data = data_mutex.lock().unwrap();
/// // This is the result of some important and long-ish work.
/// let result = data.iter().fold(0, |acc, x| acc + x * 2);
/// data.push(result);
/// // We drop the `data` explicitely because it's not necessary anymore
Comment thread
poliorcetics marked this conversation as resolved.
Outdated
/// // and the thread still has work to do. This allow other threads to
/// // start working on the data immediately, without waiting
/// // for the rest of the unrelated work to be done here.
/// //
/// // It's even more important here because we `.join` the threads after that.
/// // If we had not dropped the lock, a thread could be waiting forever for
/// // it, causing a deadlock.
/// std::mem::drop(data);
Comment thread
poliorcetics marked this conversation as resolved.
Outdated
/// // Here the lock is not assigned to a variable and so, even if the scope
Comment thread
poliorcetics marked this conversation as resolved.
Outdated
/// // does not end after this line, the mutex is still released:
/// // there is no deadlock.
/// *res_mutex.lock().unwrap() += result;
Comment thread
poliorcetics marked this conversation as resolved.
///
/// threads.into_iter().for_each(|thread| {
/// thread
/// .join()
/// .expect("The thread creating or execution failed !")
/// });
///
/// assert_eq!(*res_mutex.lock().unwrap(), 800);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "mutex_type")]
pub struct Mutex<T: ?Sized> {
Expand Down