读写锁shared_mutex
是一种较一般化的互斥锁,主要用于读操作比较多、写操作少的多线程情况,也就是可以有多个读线程和一个写线程对共享区域操作。读写锁有三种状态:读锁、写锁、不锁。遵循写互斥,读共享,写优先的原则。
常见的有下面几种情况:
- 多个线程可以同时占有读锁
- 每次只能有一个写线程,一个线程加了写锁,其他线程无论读写都要阻塞,解锁后,优先唤醒占有写锁的线程
- 一个线程加读锁,所有试图加读锁的线程都可以访问,试图加写锁的线程阻塞。也就是读共享,写互斥。 解锁后,要加写锁的线程优先。
boost中的shared_mutex
默认的实现是写者优先。 读写锁在使用前要初始化,释放底层内存前要销毁。
shared_lock
和 unique_lock
适用场景:对数据的读次数多于写次数的场合,比如数据库,我们允许在数据库上同时执行多个读操作,但是某一时刻只能在数据库上有一个写操作来更新数据。
1 |
|
某次的结果:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16线程read_1进入临界区,global_num = 10
线程read_2进入临界区,global_num = 10
线程read_1离开临界区...
线程read_2离开临界区...
线程writer_1进入临界区,global_num = 11
线程writer_1离开临界区...
线程writer_2进入临界区,global_num = 12
线程writer_2离开临界区...
线程read_2进入临界区,global_num = 12
线程read_2离开临界区...
线程read_1进入临界区,global_num = 12
线程read_1离开临界区...
线程writer_2进入临界区,global_num = 13
线程writer_2离开临界区...
线程writer_1进入临界区,global_num = 14
线程writer_1离开临界区...
由此可见,多个读线程可以同时进入临界区;写线程进入后,其他线程都不能进入,只能等它离开。即同时只有一个写线程能进入临界区。
需要避免这样的结果,也就是一个写线程连续执行,轮不到读线程了1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19线程read_1进入临界区,global_num = 10
线程read_2进入临界区,global_num = 10
线程read_1离开临界区...
线程read_2离开临界区...
线程writer_1进入临界区,global_num = 11
线程writer_1离开临界区...
线程writer_1进入临界区,global_num = 12
线程writer_1离开临界区...
线程writer_1进入临界区,global_num = 13
线程writer_1离开临界区...
线程writer_2进入临界区,global_num = 14
线程writer_2离开临界区...
线程writer_2进入临界区,global_num = 15
线程writer_2离开临界区...
线程writer_2进入临界区,global_num = 16
线程writer_2离开临界区...
线程writer_2进入临界区,global_num = 17
参考:
读写锁