1*c1396d27SGou Ngai# RwLock读写锁 2*c1396d27SGou Ngai:::{note} 3*c1396d27SGou Ngai本文作者: sujintao 4*c1396d27SGou Ngai 5*c1396d27SGou NgaiEmail: <sujintao@dragonos.org> 6*c1396d27SGou Ngai::: 7*c1396d27SGou Ngai 8*c1396d27SGou Ngai## 1. 简介 9*c1396d27SGou Ngai  读写锁是一种在并发环境下保护多进程间共享数据的机制. 相比于普通的spinlock,读写锁将对 10*c1396d27SGou Ngai共享数据的访问分为读和写两种类型: 只读取共享数据的访问使用读锁控制,修改共享数据的访问使用 11*c1396d27SGou Ngai写锁控制. 读写锁设计允许同时存在多个"读者"(只读取共享数据的访问)和一个"写者"(修改共享数据 12*c1396d27SGou Ngai的访问), 对于一些大部分情况都是读访问的共享数据来说,使用读写锁控制访问可以一定程度上提升性能. 13*c1396d27SGou Ngai 14*c1396d27SGou Ngai## 2. DragonOS中读写锁的实现 15*c1396d27SGou Ngai### 2.1 读写锁的机理 16*c1396d27SGou Ngai  读写锁的目的是维护多线程系统中的共享变量的一致性. 数据会被包裹在一个RwLock的数据结构中, 一切的访问必须通过RwLock的数据结构进行访问和修改. 每个要访问共享数据的会获得一个守卫(guard), 只读进程获得READER(读者守卫),需要修改共享变量的进程获得WRITER(写者守卫),作为RwLock的"影子", 线程都根据guard来进行访问和修改操作. 17*c1396d27SGou Ngai 18*c1396d27SGou Ngai  在实践中, 读写锁除了READER, WRITER, 还增加了UPGRADER; 这是一种介于READER和WRITER之间的守卫, 这个守卫的作用就是防止WRITER的饿死(Staration).当进程获得UPGRADER时,进程把它当成READER来使用;但是UPGRADER可以进行升级处理,升级后的UPGRADER相当于是一个WRITER守卫,可以对共享数据执行写操作. 19*c1396d27SGou Ngai 20*c1396d27SGou Ngai  所有守卫都满足rust原生的RAII机理,当守卫所在的作用域结束时,守卫将自动释放. 21*c1396d27SGou Ngai 22*c1396d27SGou Ngai### 2.2 读写锁守卫之间的关系 23*c1396d27SGou Ngai  同一时间点, 可以存在多个READER, 即可以同时有多个进程对共享数据进行访问;同一时间只能存在一个WRITER,而且当有一个进程获得WRITER时,不能存在READER和UPGRADER;进程获得UPGRADER的前提条件是,不能有UPGRADER或WRITER存在,但是当有一个进程获得UPGRADER时,进程无法成功申请READER. 24*c1396d27SGou Ngai 25*c1396d27SGou Ngai### 2.3 设计的细节 26*c1396d27SGou Ngai 27*c1396d27SGou Ngai#### 2.3.1 RwLock数据结构 28*c1396d27SGou Ngai```rust 29*c1396d27SGou Ngaipub struct RwLock<T> { 30*c1396d27SGou Ngai lock: AtomicU32,//原子变量 31*c1396d27SGou Ngai data: UnsafeCell<T>, 32*c1396d27SGou Ngai} 33*c1396d27SGou Ngai``` 34*c1396d27SGou Ngai#### 2.3.2 READER守卫的数据结构 35*c1396d27SGou Ngai```rust 36*c1396d27SGou Ngaipub struct RwLockReadGuard<'a, T: 'a> { 37*c1396d27SGou Ngai data: *const T, 38*c1396d27SGou Ngai lock: &'a AtomicU32, 39*c1396d27SGou Ngai} 40*c1396d27SGou Ngai``` 41*c1396d27SGou Ngai 42*c1396d27SGou Ngai#### 2.3.3 UPGRADER守卫的数据结构 43*c1396d27SGou Ngai```rust 44*c1396d27SGou Ngaipub struct RwLockUpgradableGuard<'a, T: 'a> { 45*c1396d27SGou Ngai data: *const T, 46*c1396d27SGou Ngai inner: &'a RwLock<T>, 47*c1396d27SGou Ngai} 48*c1396d27SGou Ngai``` 49*c1396d27SGou Ngai 50*c1396d27SGou Ngai#### 2.3.4 WRITER守卫的数据结构 51*c1396d27SGou Ngai```rust 52*c1396d27SGou Ngaipub struct RwLockWriteGuard<'a, T: 'a> { 53*c1396d27SGou Ngai data: *mut T, 54*c1396d27SGou Ngai inner: &'a RwLock<T>, 55*c1396d27SGou Ngai} 56*c1396d27SGou Ngai``` 57*c1396d27SGou Ngai 58*c1396d27SGou Ngai#### 2.3.5 RwLock的lock的结构介绍 59*c1396d27SGou Ngailock是一个32位原子变量AtomicU32, 它的比特位分配如下: 60*c1396d27SGou Ngai``` 61*c1396d27SGou Ngai UPGRADER_BIT WRITER_BIT 62*c1396d27SGou Ngai ^ ^ 63*c1396d27SGou NgaiOVERFLOW_BIT +------+ +-------+ 64*c1396d27SGou Ngai ^ | | 65*c1396d27SGou Ngai | | | 66*c1396d27SGou Ngai+-+--+--------------------------------------------------------+-+--+-+--+ 67*c1396d27SGou Ngai| | | | | 68*c1396d27SGou Ngai| | | | | 69*c1396d27SGou Ngai| | The number of the readers | | | 70*c1396d27SGou Ngai| | | | | 71*c1396d27SGou Ngai+----+--------------------------------------------------------+----+----+ 72*c1396d27SGou Ngai 31 30 2 1 0 73*c1396d27SGou Ngai``` 74*c1396d27SGou Ngai 75*c1396d27SGou Ngai  (从右到左)第0位表征WRITER是否有效,若WRITER_BIT=1, 则存在一个进程获得了WRITER守卫; 若UPGRADER_BIT=1, 则存在一个进程获得了UPGRADER守卫,第2位到第30位用来二进制表示获得READER守卫的进程数; 第31位是溢出判断位, 若OVERFLOW_BIT=1, 则不再接受新的读者守卫的获得申请. 76*c1396d27SGou Ngai 77*c1396d27SGou Ngai 78*c1396d27SGou Ngai## 3. 读写锁的主要API 79*c1396d27SGou Ngai### 3.1 RwLock的主要API 80*c1396d27SGou Ngai```rust 81*c1396d27SGou Ngai///功能: 输入需要保护的数据类型data,返回一个新的RwLock类型. 82*c1396d27SGou Ngaipub const fn new(data: T) -> Self 83*c1396d27SGou Ngai``` 84*c1396d27SGou Ngai```rust 85*c1396d27SGou Ngai///功能: 获得READER守卫 86*c1396d27SGou Ngaipub fn read(&self) -> RwLockReadGuard<T> 87*c1396d27SGou Ngai``` 88*c1396d27SGou Ngai```rust 89*c1396d27SGou Ngai///功能: 尝试获得READER守卫 90*c1396d27SGou Ngaipub fn try_read(&self) -> Option<RwLockReadGuard<T>> 91*c1396d27SGou Ngai``` 92*c1396d27SGou Ngai```rust 93*c1396d27SGou Ngai///功能: 获得WRITER守卫 94*c1396d27SGou Ngaipub fn write(&self) -> RwLockWriteGuard<T> 95*c1396d27SGou Ngai``` 96*c1396d27SGou Ngai```rust 97*c1396d27SGou Ngai///功能: 尝试获得WRITER守卫 98*c1396d27SGou Ngaipub fn try_write(&self) -> Option<RwLockWriteGuard<T>> 99*c1396d27SGou Ngai``` 100*c1396d27SGou Ngai```rust 101*c1396d27SGou Ngai///功能: 获得UPGRADER守卫 102*c1396d27SGou Ngaipub fn upgradeable_read(&self) -> RwLockUpgradableGuard<T> 103*c1396d27SGou Ngai``` 104*c1396d27SGou Ngai```rust 105*c1396d27SGou Ngai///功能: 尝试获得UPGRADER守卫 106*c1396d27SGou Ngaipub fn try_upgradeable_read(&self) -> Option<RwLockUpgradableGuard<T>> 107*c1396d27SGou Ngai``` 108*c1396d27SGou Ngai### 3.2 WRITER守卫RwLockWriteGuard的主要API 109*c1396d27SGou Ngai```rust 110*c1396d27SGou Ngai///功能: 将WRITER降级为READER 111*c1396d27SGou Ngaipub fn downgrade(self) -> RwLockReadGuard<'rwlock, T> 112*c1396d27SGou Ngai``` 113*c1396d27SGou Ngai```rust 114*c1396d27SGou Ngai///功能: 将WRITER降级为UPGRADER 115*c1396d27SGou Ngaipub fn downgrade_to_upgradeable(self) -> RwLockUpgradableGuard<'rwlock, T> 116*c1396d27SGou Ngai``` 117*c1396d27SGou Ngai### 3.3 UPGRADER守卫RwLockUpgradableGuard的主要API 118*c1396d27SGou Ngai```rust 119*c1396d27SGou Ngai///功能: 将UPGRADER升级为WRITER 120*c1396d27SGou Ngaipub fn upgrade(mut self) -> RwLockWriteGuard<'rwlock, T> 121*c1396d27SGou Ngai``` 122*c1396d27SGou Ngai```rust 123*c1396d27SGou Ngai///功能: 将UPGRADER降级为READER 124*c1396d27SGou Ngaipub fn downgrade(self) -> RwLockReadGuard<'rwlock, T> 125*c1396d27SGou Ngai``` 126*c1396d27SGou Ngai 127*c1396d27SGou Ngai## 4. 用法实例 128*c1396d27SGou Ngai```rust 129*c1396d27SGou Ngaistatic LOCK: RwLock<u32> = RwLock::new(100 as u32); 130*c1396d27SGou Ngai 131*c1396d27SGou Ngaifn t_read1() { 132*c1396d27SGou Ngai let guard = LOCK.read(); 133*c1396d27SGou Ngai let value = *guard; 134*c1396d27SGou Ngai let readers_current = LOCK.reader_count(); 135*c1396d27SGou Ngai let writers_current = LOCK.writer_count(); 136*c1396d27SGou Ngai println!( 137*c1396d27SGou Ngai "Reader1: the value is {value} 138*c1396d27SGou Ngai There are totally {writers_current} writers, {readers_current} readers" 139*c1396d27SGou Ngai ); 140*c1396d27SGou Ngai} 141*c1396d27SGou Ngai 142*c1396d27SGou Ngaifn t_read2() { 143*c1396d27SGou Ngai let guard = LOCK.read(); 144*c1396d27SGou Ngai let value = *guard; 145*c1396d27SGou Ngai let readers_current = LOCK.reader_count(); 146*c1396d27SGou Ngai let writers_current = LOCK.writer_count(); 147*c1396d27SGou Ngai println!( 148*c1396d27SGou Ngai "Reader2: the value is {value} 149*c1396d27SGou Ngai There are totally {writers_current} writers, {readers_current} readers" 150*c1396d27SGou Ngai ); 151*c1396d27SGou Ngai} 152*c1396d27SGou Ngai 153*c1396d27SGou Ngaifn t_write() { 154*c1396d27SGou Ngai let mut guard = LOCK.write(); 155*c1396d27SGou Ngai *guard += 100; 156*c1396d27SGou Ngai let writers_current = LOCK.writer_count(); 157*c1396d27SGou Ngai let readers_current = LOCK.reader_count(); 158*c1396d27SGou Ngai println!( 159*c1396d27SGou Ngai "Writers: the value is {guard} 160*c1396d27SGou Ngai There are totally {writers_current} writers, {readers_current} readers", 161*c1396d27SGou Ngai guard = *guard 162*c1396d27SGou Ngai ); 163*c1396d27SGou Ngai let read_guard=guard.downgrade(); 164*c1396d27SGou Ngai let value=*read_guard; 165*c1396d27SGou Ngai println!("After downgraded to read_guard: {value}"); 166*c1396d27SGou Ngai} 167*c1396d27SGou Ngai 168*c1396d27SGou Ngaifn t_upgrade() { 169*c1396d27SGou Ngai let guard = LOCK.upgradeable_read(); 170*c1396d27SGou Ngai let value = *guard; 171*c1396d27SGou Ngai let readers_current = LOCK.reader_count(); 172*c1396d27SGou Ngai let writers_current = LOCK.writer_count(); 173*c1396d27SGou Ngai println!( 174*c1396d27SGou Ngai "Upgrader1 before upgrade: the value is {value} 175*c1396d27SGou Ngai There are totally {writers_current} writers, {readers_current} readers" 176*c1396d27SGou Ngai ); 177*c1396d27SGou Ngai let mut upgraded_guard = guard.upgrade(); 178*c1396d27SGou Ngai *upgraded_guard += 100; 179*c1396d27SGou Ngai let writers_current = LOCK.writer_count(); 180*c1396d27SGou Ngai let readers_current = LOCK.reader_count(); 181*c1396d27SGou Ngai println!( 182*c1396d27SGou Ngai "Upgrader1 after upgrade: the value is {temp} 183*c1396d27SGou Ngai There are totally {writers_current} writers, {readers_current} readers", 184*c1396d27SGou Ngai temp = *upgraded_guard 185*c1396d27SGou Ngai ); 186*c1396d27SGou Ngai let downgraded_guard=upgraded_guard.downgrade_to_upgradeable(); 187*c1396d27SGou Ngai let value=*downgraded_guard; 188*c1396d27SGou Ngai println!("value after downgraded: {value}"); 189*c1396d27SGou Ngai let read_guard=downgraded_guard.downgrade(); 190*c1396d27SGou Ngai let value_=*read_guard; 191*c1396d27SGou Ngai println!("value after downgraded to read_guard: {value_}"); 192*c1396d27SGou Ngai} 193*c1396d27SGou Ngai 194*c1396d27SGou Ngaifn main() { 195*c1396d27SGou Ngai let r2=thread::spawn(t_read2); 196*c1396d27SGou Ngai let r1 = thread::spawn(t_read1); 197*c1396d27SGou Ngai let t1 = thread::spawn(t_write); 198*c1396d27SGou Ngai let g1 = thread::spawn(t_upgrade); 199*c1396d27SGou Ngai r1.join().expect("r1"); 200*c1396d27SGou Ngai t1.join().expect("t1"); 201*c1396d27SGou Ngai g1.join().expect("g1"); 202*c1396d27SGou Ngai r2.join().expect("r2"); 203*c1396d27SGou Ngai} 204*c1396d27SGou Ngai```