Структура RwLock
Описание: Блокировка "читатель-писатель" (reader-writer lock)
Этот тип блокировки позволяет нескольким читателям или не более чем одному писателю в любой момент времени. Часть записи этой блокировки обычно позволяет изменять базовые данные (эксклюзивный доступ), а часть чтения обычно позволяет только чтение (разделяемый доступ).
В отличие от Mutex, который не различает читателей и писателей, блокируя все потоки, ожидающие освобождения блокировки, RwLock позволяет любому количеству читателей получить блокировку, пока писатель не удерживает её.
Политика приоритетов блокировки зависит от реализации базовой операционной системы, и этот тип не гарантирует использование какой-либо конкретной политики.
Стабильность: 1.0.0
Отравление (Poisoning)
RwLock, как и Mutex, обычно становится "отравленным" при панике. Однако RwLock может быть отравлен только если паника происходит во время эксклюзивной блокировки (режим записи). Если паника происходит в любом читателе, блокировка не будет отравлена.
Примеры
#![allow(unused)] fn main() { use std::sync::RwLock; let lock = RwLock::new(5); // множество блокировок чтения может удерживаться одновременно { let r1 = lock.read().unwrap(); let r2 = lock.read().unwrap(); assert_eq!(*r1, 5); assert_eq!(*r2, 5); } // блокировки чтения снимаются здесь // только одна блокировка записи может удерживаться { let mut w = lock.write().unwrap(); *w += 1; assert_eq!(*w, 6); } // блокировка записи снимается здесь }
Методы
new (стабильность: 1.0.0, const с 1.63.0)
#![allow(unused)] fn main() { pub const fn new(t: T) -> RwLock<T> }
Создает новый экземпляр RwLock<T> в разблокированном состоянии.
get_cloned (экспериментальный)
#![allow(unused)] fn main() { pub fn get_cloned(&self) -> Result<T, PoisonError<()>> }
Возвращает содержащееся значение путем его клонирования.
Ошибки: Возвращает ошибку, если RwLock отравлен.
set (экспериментальный)
#![allow(unused)] fn main() { pub fn set(&self, value: T) -> Result<(), PoisonError<T>> }
Устанавливает содержащееся значение.
Ошибки: Возвращает ошибку, содержащую предоставленное value, если RwLock отравлен.
replace (экспериментальный)
#![allow(unused)] fn main() { pub fn replace(&self, value: T) -> LockResult<T> }
Заменяет содержащееся значение на value и возвращает старое значение.
Ошибки: Возвращает ошибку, содержащую предоставленное value, если RwLock отравлен.
impl<T: ?Sized> RwLock<T>
read (стабильность: 1.0.0)
#![allow(unused)] fn main() { pub fn read(&self) -> LockResult<RwLockReadGuard<'_, T>> }
Блокирует этот RwLock с разделяемым доступом на чтение, блокируя текущий поток до получения доступа.
Возвращает RAII-гард, который снимет разделяемый доступ при удалении.
Ошибки: Возвращает ошибку, если RwLock отравлен.
#![allow(unused)] fn main() { use std::sync::{Arc, RwLock}; use std::thread; let lock = Arc::new(RwLock::new(1)); let c_lock = Arc::clone(&lock); let n = lock.read().unwrap(); assert_eq!(*n, 1); thread::spawn(move || { let r = c_lock.read(); assert!(r.is_ok()); }).join().unwrap(); }
try_read (стабильность: 1.0.0)
#![allow(unused)] fn main() { pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<'_, T>> }
Пытается получить этот RwLock с разделяемым доступом на чтение.
Не блокирует поток. Возвращает WouldBlock, если блокировка уже захвачена эксклюзивно.
#![allow(unused)] fn main() { use std::sync::RwLock; let lock = RwLock::new(1); match lock.try_read() { Ok(n) => assert_eq!(*n, 1), Err(_) => unreachable!(), }; }
write (стабильность: 1.0.0)
#![allow(unused)] fn main() { pub fn write(&self) -> LockResult<RwLockWriteGuard<'_, T>> }
Блокирует этот RwLock с эксклюзивным доступом на запись, блокируя текущий поток до получения доступа.
Возвращает RAII-гард, который снимет доступ на запись при удалении.
Ошибки: Возвращает ошибку, если RwLock отравлен.
#![allow(unused)] fn main() { use std::sync::RwLock; let lock = RwLock::new(1); let mut n = lock.write().unwrap(); *n = 2; assert!(lock.try_read().is_err()); }
try_write (стабильность: 1.0.0)
#![allow(unused)] fn main() { pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<'_, T>> }
Пытается заблокировать этот RwLock с эксклюзивным доступом на запись.
Не блокирует поток. Возвращает WouldBlock, если блокировка уже захвачена.
#![allow(unused)] fn main() { use std::sync::RwLock; let lock = RwLock::new(1); let n = lock.read().unwrap(); assert_eq!(*n, 1); assert!(lock.try_write().is_err()); }
is_poisoned (стабильность: 1.2.0)
#![allow(unused)] fn main() { pub fn is_poisoned(&self) -> bool }
Определяет, отравлена ли блокировка.
Не следует доверять значению false для корректности программы без дополнительной синхронизации.
#![allow(unused)] fn main() { use std::sync::{Arc, RwLock}; use std::thread; let lock = Arc::new(RwLock::new(0)); let c_lock = Arc::clone(&lock); let _ = thread::spawn(move || { let _lock = c_lock.write().unwrap(); panic!(); // the lock gets poisoned }).join(); assert_eq!(lock.is_poisoned(), true); }
clear_poison (стабильность: 1.77.0)
#![allow(unused)] fn main() { pub fn clear_poison(&self) }
Очищает отравленное состояние блокировки.
Позволяет восстановиться из отравленного состояния и отметить это.
#![allow(unused)] fn main() { use std::sync::{Arc, RwLock}; use std::thread; let lock = Arc::new(RwLock::new(0)); let c_lock = Arc::clone(&lock); let _ = thread::spawn(move || { let _lock = c_lock.write().unwrap(); panic!(); // the lock gets poisoned }).join(); assert_eq!(lock.is_poisoned(), true); let guard = lock.write().unwrap_or_else(|mut e| { **e.get_mut() = 1; lock.clear_poison(); e.into_inner() }); assert_eq!(lock.is_poisoned(), false); assert_eq!(*guard, 1); }
into_inner (стабильность: 1.6.0)
#![allow(unused)] fn main() { pub fn into_inner(self) -> LockResult<T> }
Потребляет этот RwLock, возвращая базовые данные.
Ошибки: Возвращает ошибку, содержащую базовые данные, если RwLock отравлен.
#![allow(unused)] fn main() { use std::sync::RwLock; let lock = RwLock::new(String::new()); { let mut s = lock.write().unwrap(); *s = "modified".to_owned(); } assert_eq!(lock.into_inner().unwrap(), "modified"); }
get_mut (стабильность: 1.6.0)
#![allow(unused)] fn main() { pub fn get_mut(&mut self) -> LockResult<&mut T> }
Возвращает изменяемую ссылку на базовые данные.
Не требует фактической блокировки, так как заимствует RwLock изменяемо.
#![allow(unused)] fn main() { use std::sync::RwLock; let mut lock = RwLock::new(0); *lock.get_mut().unwrap() = 10; assert_eq!(*lock.read().unwrap(), 10); }
data_ptr (экспериментальный)
#![allow(unused)] fn main() { pub const fn data_ptr(&self) -> *mut T }
Возвращает сырой указатель на базовые данные.
Пользователь несет ответственность за правильную синхронизацию операций чтения/записи.
Реализации трейтов
Debug (стабильность: 1.0.0)
Реализует форматирование для отладки (где T: Debug).
Default (стабильность: 1.10.0)
Создает новый RwLock<T> со значением по умолчанию для T (где T: Default).
From<T> (стабильность: 1.24.0)
Создает новый экземпляр RwLock<T> в разблокированном состоянии. Эквивалентно RwLock::new.
Безопасность потоков
Send(где T: Send)Sync(где T: Send + Sync)RefUnwindSafeUnwindSafe
Автоматические реализации трейтов
!FreezeUnpin(где T: Unpin)
Стандартные реализации
AnyBorrow<T>BorrowMut<T>From<!>From<T>Into<U>TryFrom<U>TryInto<U>