Struct std :: sync :: Mutex 1.0.0 [ ] [src]

pub struct Mutex<T: ?Sized> { /* fields omitted */ }
Expand description

互斥原语可用于保护共享数据

此互斥锁将阻止等待锁可用的线程。互斥锁也可以通过 new 构造函数进行静态初始化或创建。 每个互斥锁都有一个类型参数,表示它正在保护的数据。 只能通过从 lock try_lock 返回的 RAII 保护来访问数据,这保证了只有在互斥锁被锁定时才可以访问数据。

Poisoning

此模块中的互斥锁实现了一种称为 “poisoning” 的策略,只要线程 panics 按住互斥锁,互斥锁就会被视为中毒。 一旦互斥锁中毒,默认情况下,所有其他线程都无法访问数据,因为它很可能已被污染 (某些不变性未得到维护)。

对于互斥锁,这意味着 lock try_lock 方法返回一个 Result ,该 Result 指示互斥锁是否已中毒。 互斥锁的大多数用法将只是 unwrap() 这些结果,从而在线程之间传播 panics 以确保不会看到可能无效的不变式。

但是,中毒的互斥锁不会阻止对底层数据的所有访问。 PoisonError 类型具有 into_inner 方法,该方法将返回保护,否则将在成功锁定后返回该保护。 尽管锁被中毒,这仍允许访问数据。

Examples

use std::sync ::{ Arc , Mutex }; use std::thread ; use std::sync::mpsc::channel ; const N : usize = 10 ; // Spawn 几个线程用于递增共享变量 (non-atomically),并在完成所有递增操作后让主线程知道。 // 在这里,我们使用 Arc 在线程之间共享内存,并且 Arc 中的数据受到互斥锁的保护。 let data = Arc::new ( Mutex::new ( 0 )); let ( tx , rx ) = channel (); for _ in 0 .. N { let ( data , tx ) = ( Arc::clone ( & data ), tx . clone ()); thread::spawn ( move | | { // 只有持有锁后,才能访问共享状态。 // 我们的非原子增量是安全的,因为当持有锁时,我们是唯一可以访问共享状态的线程。 // 我们用 unwrap() 的返回值来断言,我们不希望线程在持有锁的同时失败。 let mut data = data . lock (). unwrap (); * data + = 1 ; if * data = = N { tx . send (()). unwrap (); // `data` 离开作用域时,此处的锁已解锁。 rx . recv (). unwrap (); Run

要从中毒的互斥锁中恢复:

use std::sync ::{ Arc , Mutex }; use std::thread ; let lock = Arc::new ( Mutex::new ( 0_u32 )); let lock2 = Arc::clone ( & lock ); let _ = thread::spawn ( move | | - > () { // 该线程将首先获取互斥锁,因为该锁尚未中毒,所以将解开 `lock` 的结果。 let _guard = lock2 . lock (). unwrap (); // 按住锁 (`_guard` 在作用域中) 时,此 panic 将中毒互斥锁。 panic! (); }). join (); // 到此为止,锁定都会中毒,但是可以对返回的结果进行模式匹配,以返回两个分支上的基础防护。 let mut guard = match lock . lock () { Ok ( guard ) = > guard , Err ( poisoned ) = > poisoned . into_inner (), * guard + = 1 ; Run

时需要手动丢弃互斥锁守卫,以便在封闭作用域结束之前将其解锁。

use std::sync ::{ Arc , Mutex }; use std::thread ; const N : usize = 3 ; let data_mutex = Arc::new ( Mutex::new ( vec! [ 1 , 2 , 3 , 4 ])); let res_mutex = Arc::new ( Mutex::new ( 0 )); let mut threads = Vec::with_capacity ( N ); ( 0 .. N ). for_each ( | _ | { 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 (); // 这是一些重要而长期的工作的结果。 let result = data . iter (). fold ( 0 , | acc , x | acc + x * 2 ); data . push ( result ); drop ( data ); * res_mutex_clone . lock (). unwrap () + = result ; let mut data = data_mutex . lock (). unwrap (); // 这是一些重要而长期的工作的结果。 let result = data . iter (). fold ( 0 , | acc , x | acc + x * 2 ); data . push ( result ); // 我们明确丢弃 `data`,因为不再需要 `data`,并且线程仍然有工作要做。 // 这允许其他线程立即开始处理数据,而无需等待其余无关工作在这里完成。 // 它在这里比在线程中更重要,因为在此之后我们对线程进行 `.join` 处理。 // 如果我们没有丢弃互斥锁守卫,则线程可能会永远等待它,从而导致死锁。 drop ( data ); // 这里互斥锁防护未分配给变量,因此,即使作用域在此行之后没有结束,互斥锁仍被释放: 没有死锁。 * res_mutex . lock (). unwrap () + = result ; threads . into_iter (). for_each ( | thread | { thread . join () . expect ( "The thread creating or execution failed !" ) assert_eq! ( * res_mutex . lock (). unwrap (), 800 ); Run

Implementations

在解锁状态下创建一个新的互斥锁,以备使用。

Examples

use std::sync::Mutex ; let mutex = Mutex::new ( 0 ); Run

获取一个互斥锁,阻塞当前线程,直到能够这样做为止。

该函数将阻塞本地线程,直到可用于获取互斥锁为止。 返回时,该线程是唯一持有锁的线程。 返回了 RAII 守卫,以允许对锁进行一定范围的解锁。 当守卫离开作用域时,互斥锁将被解锁。

未指定将互斥锁锁定在已经持有该锁的线程中的确切行为。 但是,该函数不会在第二次调用时返回 (例如,可能为 panic 或死锁)。

Errors

如果互斥锁的另一个用户在握住互斥锁时恐慌,则一旦获取互斥锁,此调用将返回错误。

Panics

如果当前线程已锁定,则调用此函数时可能为 panic。

Examples

use std::sync ::{ Arc , Mutex }; use std::thread ; let mutex = Arc::new ( Mutex::new ( 0 )); let c_mutex = Arc::clone ( & mutex ); thread::spawn ( move | | { * c_mutex . lock (). unwrap () = 10 ; }). join (). expect ( "thread::spawn failed" ); assert_eq! ( * mutex . lock (). unwrap (), 10 ); Run

尝试获取此锁。

如果此时无法获取锁,则返回 Err 。 否则,将返回 RAII 守卫。当守卫被丢弃时,锁将被解锁。

该函数不会阻止。

Errors

如果该调用的另一个用户同时持有互斥锁,则该调用将返回 Poisoned 错误,否则将获得该调用的拒绝互锁。

如果互斥锁已被锁定而无法获取,则该调用将返回 WouldBlock 错误。

Examples

use std::sync ::{ Arc , Mutex }; use std::thread ; let mutex = Arc::new ( Mutex::new ( 0 )); let c_mutex = Arc::clone ( & mutex ); thread::spawn ( move | | { let mut lock = c_mutex . try_lock (); if let Ok ( ref mut mutex ) = lock { * * mutex = 10 ; } else { println! ( "try_lock failed" ); }). join (). expect ( "thread::spawn failed" ); assert_eq! ( * mutex . lock (). unwrap (), 10 ); Run
🔬 This is a nightly-only experimental API. ( mutex_unlock #81872 )

立即丢弃这个守卫,从而解锁互斥锁。

此函数等效于在守卫上调用 drop ,但更具自记录性。 或者,守卫离开作用域时将自动丢弃。

#![ feature ( mutex_unlock )] use std::sync::Mutex ; let mutex = Mutex::new ( 0 ); let mut guard = mutex . lock (). unwrap (); * guard + = 20 ; Mutex::unlock ( guard ); Run

确定互斥锁是否中毒。

如果另一个线程处于活动状态,则互斥锁仍可随时中毒。 如果没有其他同步,则不应信任 false 值来确保程序正确性。

Examples

use std::sync ::{ Arc , Mutex }; use std::thread ; let mutex = Arc::new ( Mutex::new ( 0 )); let c_mutex = Arc::clone ( & mutex ); let _ = thread::spawn ( move | | { let _lock = c_mutex . lock (). unwrap (); panic! (); // 互斥锁中毒 }). join (); assert_eq! ( mutex . is_poisoned (), true ); Run

使用此互斥锁,返回基础数据。

Errors

如果此互斥锁的另一个用户在按住互斥锁时恐慌,则此调用将返回错误。

Examples

use std::sync::Mutex ; let mutex = Mutex::new ( 0 ); assert_eq! ( mutex . into_inner (). unwrap (), 0 ); Run

返回对基础数据的可变引用。

由于此调用借用 Mutex 是可变的,因此不需要进行实际的锁定 - 可变借用可以静态地保证不存在任何锁定。

Errors

如果此互斥锁的另一个用户在按住互斥锁时恐慌,则此调用将返回错误。

Examples

use std::sync::Mutex ; let mut mutex = Mutex::new ( 0 ); * mutex . get_mut (). unwrap () = 10 ; assert_eq! ( * mutex . lock (). unwrap (), 10 ); Run

Trait Implementations

使用给定的格式化程序格式化该值。 Read more

创建一个 Mutex<T> ,其 T 值为 Default

在解锁状态下创建一个新的互斥锁,以备使用。 这等效于 Mutex::new

Auto Trait Implementations

Blanket Implementations

获取 self TypeId Read more

从拥有的值中一成不变地借用。 Read more

从拥有的值中借用。 Read more

执行转换。

执行转换。