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