pub struct RwLock<T: ?Sized> { /* private fields */ }展开描述
一个异步的读者-写者锁。
此类锁
允许
任意数量的 reader
或
最多一个 writer
在同一时间
持有。
此锁的
write
部分
通常允许
修改
底层数据
(独占访问),
此锁的
read 部分
通常
允许
只读访问
(共享访问)。
相比之下,
不
区分
获取锁的
reader
或 writer,
因此
会导致
任何
等待锁可用
的任务
让出。
Mutex
则允许
任意数量的 reader
获取锁,
只要
没有 writer
持有该锁。RwLock
Tokio 的
读-写锁的
优先级策略
是
公平
的
(或
优先写),
以确保
reader
不会
饿死
writer。
公平性
通过
等待锁的
任务的
先进先出队列
来保证;
在
其之前排队的
所有
write
锁请求
被获取
并释放
之前,
不会
授予读锁。
与
Rust 标准库的
相比,
后者的
优先级策略
取决于
操作系统
的实现。std::sync::RwLock
类型参数
表示
此锁保护的数据。
需要
T
满足
T
才能
returned from the locking methods implement Send
(and Deref
for the DerefMut methods) to allow access to the content of the lock.write
§示例
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>
impl<T: ?Sized> RwLock<T>
Sourcepub fn with_max_readers(value: T, max_reads: u32) -> RwLock<T>where
T: Sized,
pub fn with_max_readers(value: T, max_reads: u32) -> RwLock<T>where
T: Sized,
Sourcepub const fn const_new(value: T) -> RwLock<T>where
T: Sized,
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);Sourcepub const fn const_with_max_readers(value: T, max_reads: u32) -> RwLock<T>where
T: Sized,
pub const fn const_with_max_readers(value: T, max_reads: u32) -> RwLock<T>where
T: Sized,
Sourcepub async fn read(&self) -> RwLockReadGuard<'_, T>
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);Sourcepub fn blocking_read(&self) -> RwLockReadGuard<'_, T>
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 insidespawn_blocking()(orblock_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());
}Sourcepub async fn read_owned(self: Arc<Self>) -> OwnedRwLockReadGuard<T>
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);
}Sourcepub fn try_read(&self) -> Result<RwLockReadGuard<'_, T>, TryLockError>
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);Sourcepub fn try_read_owned(
self: Arc<Self>,
) -> Result<OwnedRwLockReadGuard<T>, TryLockError>
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);Sourcepub async fn write(&self) -> RwLockWriteGuard<'_, T>
pub async fn write(&self) -> RwLockWriteGuard<'_, T>
Sourcepub fn blocking_write(&self) -> RwLockWriteGuard<'_, T>
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 insidespawn_blocking()(orblock_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);
}Sourcepub async fn write_owned(self: Arc<Self>) -> OwnedRwLockWriteGuard<T>
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;
}Sourcepub fn try_write(&self) -> Result<RwLockWriteGuard<'_, T>, TryLockError>
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());Sourcepub fn try_write_owned(
self: Arc<Self>,
) -> Result<OwnedRwLockWriteGuard<T>, TryLockError>
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());Sourcepub fn get_mut(&mut self) -> &mut T
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;
}Sourcepub fn into_inner(self) -> Twhere
T: Sized,
pub fn into_inner(self) -> Twhere
T: Sized,
消耗此锁,返回底层数据。