跳到主要内容

RwLock

搜索

结构体 RwLock 

Source
pub struct RwLock<T: ?Sized> { /* private fields */ }
展开描述

一个异步的读者-写者锁。

此类锁 允许 任意数量的 reader 或 最多一个 writer 在同一时间 持有。 此锁的 write 部分 通常允许 修改 底层数据 (独占访问), 此锁的 read 部分 通常 允许 只读访问 (共享访问)。

相比之下, Mutex 不 区分 获取锁的 reader 或 writer, 因此 会导致 任何 等待锁可用 的任务 让出。 RwLock 则允许 任意数量的 reader 获取锁, 只要 没有 writer 持有该锁。

Tokio 的 读-写锁的 优先级策略 是 公平 的 (或 优先写), 以确保 reader 不会 饿死 writer。 公平性 通过 等待锁的 任务的 先进先出队列 来保证; 在 其之前排队的 所有 write 锁请求 被获取 并释放 之前, 不会 授予读锁。 与 Rust 标准库的 std::sync::RwLock 相比, 后者的 优先级策略 取决于 操作系统 的实现。

类型参数 T 表示 此锁保护的数据。 需要 T 满足 Send 才能 returned from the locking methods implement Deref (and DerefMut for the write methods) to allow access to the content of the lock.

§示例

use tokio::sync::RwLock;













let lock = RwLock::new(5);













// many reader locks can be held at once






{






    let r1 = lock.read().await;






    let r2 = lock.read().await;






    assert_eq!(*r1, 5);






    assert_eq!(*r2, 5);






} // read locks are dropped at this point













// only one write lock may be held, however






{






    let mut w = lock.write().await;






    *w += 1;






    assert_eq!(*w, 6);






} // write lock is dropped here

实现§

Source§

impl<T: ?Sized> RwLock<T>

Source

pub fn new(value: T) -> RwLock<T>
where T: Sized,

创建一个新的 RwLock 实例,处于未锁定状态。

§示例
use tokio::sync::RwLock;













let lock = RwLock::new(5);
Source

pub fn with_max_readers(value: T, max_reads: u32) -> RwLock<T>
where T: Sized,

创建一个新的 RwLock 实例,处于未锁定状态,最多允许 max_reads 个并发读者。

§示例
use tokio::sync::RwLock;













let lock = RwLock::with_max_readers(5, 1024);
§Panics

如果 max_reads0 或大于 u32::MAX >> 3 则会 panic。

Source

pub const fn const_new(value: T) -> RwLock<T>
where T: Sized,

创建一个新的 RwLock 实例,处于未锁定状态。

使用 tracing 不稳定特性时,通过 const_new 创建的 RwLock 不会被插桩。因此,它不会出现在 tokio-console 中。如有需要,请改用 RwLock::new 来创建可插桩的对象。

§示例
use tokio::sync::RwLock;













static LOCK: RwLock<i32> = RwLock::const_new(5);
Source

pub const fn const_with_max_readers(value: T, max_reads: u32) -> RwLock<T>
where T: Sized,

创建一个新的 RwLock 实例,处于未锁定状态,最多允许 max_reads 个并发读者。

§示例
use tokio::sync::RwLock;













static LOCK: RwLock<i32> = RwLock::const_with_max_readers(5, 1024);
§Panics

如果 max_reads0 或大于 u32::MAX >> 3 则会 panic。

Source

pub async fn read(&self) -> RwLockReadGuard<'_, T>

以共享读访问方式锁定此 RwLock,使当前任务挂起直到获取到读锁。

调用任务将挂起直到持有锁的写者释放。当任务恢复时,锁内可能还有其他读者。

请注意,根据 RwLock 的优先级策略,在先前的写锁释放之前不会授予读锁,以防止饥饿。因此,如果当前任务持有读锁、尝试获取写锁,然后当前任务再尝试获取读锁,则可能发生死锁。

返回一个 RAII guard,当它被逐出时会释弃对 RwLock 的读访问权。

§Cancel safety

此方法使用队列按请求顺序公平分配锁。取消对 read 的调用会丢失在队列中的位置。

§示例
use std::sync::Arc;






use tokio::sync::RwLock;













let lock = Arc::new(RwLock::new(1));






let c_lock = lock.clone();













let n = lock.read().await;






assert_eq!(*n, 1);













tokio::spawn(async move {






    // While main has an active read lock, we acquire one too.






    let r = c_lock.read().await;






    assert_eq!(*r, 1);






}).await.expect("The spawned task has panicked");













// Drop the guard after the spawned task finishes.






drop(n);
Source

pub fn blocking_read(&self) -> RwLockReadGuard<'_, T>

阻塞地以共享读访问方式锁定此 RwLock

此方法用于需要在异步代码和同步代码中都使用此 rwlock 的场景。

返回一个 RAII guard,丢弃时会释放此 RwLock 的读访问。

§Panics

如果在异步执行上下文中调用此函数会触发 panic。

  • If you find yourself in an asynchronous execution context and needing to call some (synchronous) function which performs one of these blocking_ operations, then consider wrapping that call inside spawn_blocking() (or block_in_place()).
§示例
use std::sync::Arc;






use tokio::sync::RwLock;













#[tokio::main]






async fn main() {






    let rwlock = Arc::new(RwLock::new(1));






    let mut write_lock = rwlock.write().await;













    let blocking_task = tokio::task::spawn_blocking({






        let rwlock = Arc::clone(&rwlock);






        move || {






            // This shall block until the `write_lock` is released.






            let read_lock = rwlock.blocking_read();






            assert_eq!(*read_lock, 0);






        }






    });













    *write_lock -= 1;






    drop(write_lock); // release the lock.













    // Await the completion of the blocking task.






    blocking_task.await.unwrap();













    // Assert uncontended.






    assert!(rwlock.try_write().is_ok());






}
Source

pub async fn read_owned(self: Arc<Self>) -> OwnedRwLockReadGuard<T>

以共享读访问方式锁定此 RwLock,使当前任务挂起直到获取到读锁。

调用任务将挂起直到持有锁的写者释放。当任务恢复时,锁内可能还有其他读者。

此方法与 RwLock::read 相同,只是返回的 guard 通过 Arc 而非借用引用 RwLock。因此,调用此方法时 RwLock 必须包装在 Arc 中,且 guard 将在 'static 生命周期内有效,因为它通过持有 Arc 保持 RwLock 存活。

请注意,根据 RwLock 的优先级策略,在先前的写锁释放之前不会授予读锁,以防止饥饿。因此,如果当前任务持有读锁、尝试获取写锁,然后当前任务再尝试获取读锁,则可能发生死锁。

返回一个 RAII guard,当它被逐出时会释弃对 RwLock 的读访问权。

§Cancel safety

此方法使用队列按请求顺序公平分配锁。取消对 read_owned 的调用会丢失在队列中的位置。

§示例
use std::sync::Arc;






use tokio::sync::RwLock;













let lock = Arc::new(RwLock::new(1));






let c_lock = lock.clone();













let n = lock.read_owned().await;






assert_eq!(*n, 1);













tokio::spawn(async move {






    // While main has an active read lock, we acquire one too.






    let r = c_lock.read_owned().await;






    assert_eq!(*r, 1);






}).await.expect("The spawned task has panicked");













// Drop the guard after the spawned task finishes.






drop(n);






}
Source

pub fn try_read(&self) -> Result<RwLockReadGuard<'_, T>, TryLockError>

尝试以共享读访问方式获取此 RwLock 的锁。

如果不能立即获取访问权限,则返回 TryLockError。否则,返回一个 RAII guard,丢弃时会释放读访问。

§示例
use std::sync::Arc;






use tokio::sync::RwLock;













let lock = Arc::new(RwLock::new(1));






let c_lock = lock.clone();













let v = lock.try_read().unwrap();






assert_eq!(*v, 1);













tokio::spawn(async move {






    // While main has an active read lock, we acquire one too.






    let n = c_lock.read().await;






    assert_eq!(*n, 1);






}).await.expect("The spawned task has panicked");













// Drop the guard when spawned task finishes.






drop(v);
Source

pub fn try_read_owned( self: Arc<Self>, ) -> Result<OwnedRwLockReadGuard<T>, TryLockError>

尝试以共享读访问方式获取此 RwLock 的锁。

如果不能立即获取访问权限,则返回 TryLockError。否则,返回一个 RAII guard,丢弃时会释放读访问。

此方法与 RwLock::try_read 相同,只是返回的 guard 通过 Arc 而非借用引用 RwLock。因此,调用此方法时 RwLock 必须包装在 Arc 中,且 guard 将在 'static 生命周期内有效,因为它通过持有 Arc 保持 RwLock 存活。

§示例
use std::sync::Arc;






use tokio::sync::RwLock;













let lock = Arc::new(RwLock::new(1));






let c_lock = lock.clone();













let v = lock.try_read_owned().unwrap();






assert_eq!(*v, 1);













tokio::spawn(async move {






    // While main has an active read lock, we acquire one too.






    let n = c_lock.read_owned().await;






    assert_eq!(*n, 1);






}).await.expect("The spawned task has panicked");













// Drop the guard when spawned task finishes.






drop(v);
Source

pub async fn write(&self) -> RwLockWriteGuard<'_, T>

以独占写访问方式锁定此 RwLock,使当前任务挂起直到获取到写锁。

调用任务将挂起直到其他持有锁的写者或读者释放。

返回一个 RAII guard,丢弃时会释放此 RwLock 的写访问。

§Cancel safety

此方法使用队列按请求顺序公平分配锁。取消对 write 的调用会丢失在队列中的位置。

§示例
use tokio::sync::RwLock;













let lock = RwLock::new(1);













let mut n = lock.write().await;






*n = 2;
Source

pub fn blocking_write(&self) -> RwLockWriteGuard<'_, T>

阻塞地以独占写访问方式锁定此 RwLock

此方法用于需要在异步代码和同步代码中都使用此 rwlock 的场景。

返回一个 RAII guard,丢弃时会释放此 RwLock 的写访问。

§Panics

如果在异步执行上下文中调用此函数会触发 panic。

  • If you find yourself in an asynchronous execution context and needing to call some (synchronous) function which performs one of these blocking_ operations, then consider wrapping that call inside spawn_blocking() (or block_in_place()).
§示例
use std::sync::Arc;






use tokio::{sync::RwLock};













#[tokio::main]






async fn main() {






    let rwlock =  Arc::new(RwLock::new(1));






    let read_lock = rwlock.read().await;













    let blocking_task = tokio::task::spawn_blocking({






        let rwlock = Arc::clone(&rwlock);






        move || {






            // This shall block until the `read_lock` is released.






            let mut write_lock = rwlock.blocking_write();






            *write_lock = 2;






        }






    });













    assert_eq!(*read_lock, 1);






    // Release the last outstanding read lock.






    drop(read_lock);













    // Await the completion of the blocking task.






    blocking_task.await.unwrap();













    // Assert uncontended.






    let read_lock = rwlock.try_read().unwrap();






    assert_eq!(*read_lock, 2);






}
Source

pub async fn write_owned(self: Arc<Self>) -> OwnedRwLockWriteGuard<T>

以独占写访问方式锁定此 RwLock,使当前任务挂起直到获取到写锁。

调用任务将挂起直到其他持有锁的写者或读者释放。

此方法与 RwLock::write 相同,只是返回的 guard 通过 Arc 而非借用引用 RwLock。因此,调用此方法时 RwLock 必须包装在 Arc 中,且 guard 将在 'static 生命周期内有效,因为它通过持有 Arc 保持 RwLock 存活。

返回一个 RAII guard,丢弃时会释放此 RwLock 的写访问。

§Cancel safety

此方法使用队列按请求顺序公平分配锁。取消对 write_owned 的调用会丢失在队列中的位置。

§示例
use std::sync::Arc;






use tokio::sync::RwLock;













let lock = Arc::new(RwLock::new(1));













let mut n = lock.write_owned().await;






*n = 2;






}
Source

pub fn try_write(&self) -> Result<RwLockWriteGuard<'_, T>, TryLockError>

尝试以独占写访问方式获取此 RwLock 的锁。

如果不能立即获取访问权限,则返回 TryLockError。否则,返回一个 RAII guard,丢弃时会释放写访问。

§示例
use tokio::sync::RwLock;













let rw = RwLock::new(1);













let v = rw.read().await;






assert_eq!(*v, 1);













assert!(rw.try_write().is_err());
Source

pub fn try_write_owned( self: Arc<Self>, ) -> Result<OwnedRwLockWriteGuard<T>, TryLockError>

尝试以独占写访问方式获取此 RwLock 的锁。

如果不能立即获取访问权限,则返回 TryLockError。否则,返回一个 RAII guard,丢弃时会释放写访问。

此方法与 RwLock::try_write 相同,只是返回的 guard 通过 Arc 而非借用引用 RwLock。因此,调用此方法时 RwLock 必须包装在 Arc 中,且 guard 将在 'static 生命周期内有效,因为它通过持有 Arc 保持 RwLock 存活。

§示例
use std::sync::Arc;






use tokio::sync::RwLock;













let rw = Arc::new(RwLock::new(1));













let v = Arc::clone(&rw).read_owned().await;






assert_eq!(*v, 1);













assert!(rw.try_write_owned().is_err());
Source

pub fn get_mut(&mut self) -> &mut T

返回对底层数据的可变引用。

由于此调用可变地借用 RwLock,不需要实际执行加锁 —— 可变借用静态保证不存在任何锁。

§示例
use tokio::sync::RwLock;













fn main() {






    let mut lock = RwLock::new(1);













    let n = lock.get_mut();






    *n = 2;






}
Source

pub fn into_inner(self) -> T
where T: Sized,

消耗此锁,返回底层数据。

Trait 实现§

Source§

impl<T> Debug for RwLock<T>
where T: Debug + ?Sized,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

使用给定的格式化器格式化此值。 更多信息
Source§

impl<T> Default for RwLock<T>
where T: Default,

Source§

fn default() -> Self

Returns the “default value” for a type. 更多信息
Source§

impl<T> From<T> for RwLock<T>

Source§

fn from(s: T) -> Self

从输入类型转换为此类型。
Source§

impl<T> Send for RwLock<T>
where T: ?Sized + Send,

Source§

impl<T> Sync for RwLock<T>
where T: ?Sized + Send + Sync,

自动 Trait 实现§

§

impl<T> !Freeze for RwLock<T>

§

impl<T> !RefUnwindSafe for RwLock<T>

§

impl<T> Unpin for RwLock<T>
where T: Unpin + ?Sized,

§

impl<T> UnsafeUnpin for RwLock<T>
where T: UnsafeUnpin + ?Sized,

§

impl<T> !UnwindSafe for RwLock<T>

Blanket 实现§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. 更多信息
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. 更多信息
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. 更多信息
Source§

impl<T> From<!> for T

Source§

fn from(t: !) -> T

从输入类型转换为此类型。
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

原样返回传入的参数。

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

调用 U::from(self)

也就是说,此转换的具体行为取决于 From<T> for U 的实现方式。

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

转换出错时返回的类型。
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

执行转换。
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

转换出错时返回的类型。
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

执行转换。