本文简单介绍 Rust 中的读写锁RwLock
,内容概览如下:
RwLock
实现std::sync::RwLock
parking_lot::RwLock
在计算机科学中,有一些经典的同步问题,读者-作家问题就是其中一个,该问题涉及多个并发线程试图同时访问同一共享资源的情况。
读者-作家问题:我们拥有一种资源(例如,数据库),可以由不修改资源的读者和可以修改资源的作家访问。当作家修改资源时,其他任何人(读者或作家)都无法同时访问它,因为另一位作家可能破坏资源,而另一位读者可能读取部分修改的值,因此可能出现不一致。
为了准确理解问题,我们先介绍一些基本概念。
临界区 Critical section,在并发编程中,对共享资源的并发访问可能导致意外或错误的行为,因此需要以某种方式保护访问共享资源的那部分程序。这部分受保护的代码片段称为临界区。
互斥量 Mutex,在多线程并发编程时,为了确保一次仅一个线程可以访问共享资源,引入了Mutex
的概念,它是 Mutual Exclusion 的缩写,通常翻译为互斥量或互斥锁。
信号量 Semaphore,同样的,为了控制并发系统中多个线程对共享资源的访问,引入了Semaphore
的概念,通常翻译为信号量。
读写锁 RWLock,在计算机科学中,读写锁是解决读者-作家问题的同步原语之一。读写锁允许读操作共享访问,而写操作则需要互斥访问。通常构造在互斥量和条件变量之上,或者构造在信号量之上。
自读者-作家问题提出以来,人们对它进行了广泛的研究,读写锁是解决读者-作家问题的方案之一,按照读写锁的锁定优先级策略分为以下三种:
标准库中的RwLock
:
同时,第三方库parking_lot中也实现了RwLock
,它与标准库的RwLock
的主要区别是:
RwLock
装箱。基本的使用,示例如下:
#[macro_use]
extern crate lazy_static;
use std::thread;
use std::sync::RwLock;
//use parking_lot::RwLock;
lazy_static! {
pub static ref INC: RwLock<i32> = RwLock::new(0);
}
fn main() {
let thread1 = thread::spawn(|| {
for i in 1..10 {
let mut w = INC.write().unwrap();
//let mut w = INC.write();
*w = *w + 1;
}
});
let thread2 = thread::spawn(|| {
for i in 1..10 {
let mut w = INC.write().unwrap();
//let mut w = INC.write();
*w = *w + 1;
}
});
thread1.join().unwrap();
thread2.join().unwrap();
let r = INC.read().unwrap();
//let r = INC.read();
println!("{}", *r); // 输出 18
}
一般项目中会有对全局配置文件的操作,示例如下:
#[macro_use]
extern crate lazy_static;
use std::sync::RwLock;
#[derive(Debug, Clone, Copy)]
pub struct MyConfig {
pub debug: bool,
pub info: &'static str,
}
lazy_static! {
pub static ref CONFIG: RwLock<MyConfig> = RwLock::new(MyConfig { debug: false, info: "Some info" });
}
impl MyConfig {
pub fn init(custom_debug: Option<bool>, custom_info: Option<&'static str>) -> Result<(), i32> {
let mut w = CONFIG.write().unwrap();
match (custom_debug , custom_info) {
(Some(debug_value), Some(custom_info)) => *w = MyConfig { debug: debug_value, info: custom_info},
_ => (),
};
Ok(())
}
pub fn global_config() -> MyConfig {
let m = CONFIG.read().unwrap();
// 返回配置的拷贝
*m
}
}
fn main() {
let a = MyConfig::global_config();
dbg!(a);
MyConfig::init(Some(true), Some("Updated"));
let a = MyConfig::global_config();
dbg!(a);
}
输出:
[src/main.rs:39] a = MyConfig {
debug: false,
info: "Some info",
}
[src/main.rs:45] a = MyConfig {
debug: true,
info: "Updated",
}
希望对大家理解RwLock
有帮助,欢迎交流,self-fulfil。
Rust异步入门 https://mp.weixin.qq.com/s/aA89BBUfM6UJYUMkOoZrig
理解智能指针 https://mp.weixin.qq.com/s/NpH-fVA_SdjpYgYkktfT5A
如何理解Rust中的变与不变 https://mp.weixin.qq.com/s/s9Ac0xfpG-KeVgPAFG-fog