xref: /DragonOS/docs/kernel/locking/rwlock.md (revision c1396d277115b371d09ad6d39a1c419f9224ffd0)
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&emsp;&emsp;读写锁是一种在并发环境下保护多进程间共享数据的机制.  相比于普通的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&emsp;&emsp;读写锁的目的是维护多线程系统中的共享变量的一致性. 数据会被包裹在一个RwLock的数据结构中, 一切的访问必须通过RwLock的数据结构进行访问和修改. 每个要访问共享数据的会获得一个守卫(guard), 只读进程获得READER(读者守卫),需要修改共享变量的进程获得WRITER(写者守卫),作为RwLock的"影子", 线程都根据guard来进行访问和修改操作.
17*c1396d27SGou Ngai
18*c1396d27SGou Ngai&emsp;&emsp;在实践中, 读写锁除了READER, WRITER, 还增加了UPGRADER; 这是一种介于READER和WRITER之间的守卫, 这个守卫的作用就是防止WRITER的饿死(Staration).当进程获得UPGRADER时,进程把它当成READER来使用;但是UPGRADER可以进行升级处理,升级后的UPGRADER相当于是一个WRITER守卫,可以对共享数据执行写操作.
19*c1396d27SGou Ngai
20*c1396d27SGou Ngai&emsp;&emsp;所有守卫都满足rust原生的RAII机理,当守卫所在的作用域结束时,守卫将自动释放.
21*c1396d27SGou Ngai
22*c1396d27SGou Ngai### 2.2 读写锁守卫之间的关系
23*c1396d27SGou Ngai&emsp;&emsp;同一时间点, 可以存在多个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&emsp;&emsp;(从右到左)第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```