Home 内核-rwlock(读写自旋锁)
Post
Cancel

内核-rwlock(读写自旋锁)

Linux内核中的读写(自旋)锁(rwlock)是一种用于线程同步的机制,用于在多线程环境中实现对共享资源的读写访问。它可以看作自旋锁(spinlock)的进阶版本,可以帮助实现更复杂的功能。

这里记录的是内核层的读写自旋锁的使用,不是应用层多线程中的读写锁。

介绍

读写(自旋)锁(rwlock)是一种高级锁机制,用于在多线程环境中实现对共享资源的读写访问。读写锁提供了更细粒度的锁定策略,以允许多个线程同时持有读锁,但只允许单个线程持有写锁

读写锁的特点:

  1. 读共享特性:多个线程可以同时持有读锁,并行地进行读取操作,不会进入忙等。读锁是共享的,适用于多个线程同时读取共享资源的情况。
  2. 写独占特性:写锁是独占的,一次只能由一个线程持有。当某个线程持有写锁时,其他线程无法获取读锁或写锁,从而保证写操作的原子性。

总结来说,有线程获取了读锁,其他线程仍可以继续获取读锁,不需要等待。如果有线程获取了写锁,那么其他线程既不能获得取锁,也不能获取写锁。 如果一个线程要获取读锁,只要没有线程获取写锁(没有线程在写),读锁就能获取成功;而一个线程要获取写锁,需要忙等,直到其他线程释放了所有的读锁和写锁。 所以,写锁获取的时间期望上会更长一些。因此,读写锁适用于读操作频繁而写操作较少的场景,才可以提高并发性和性能。

实际性能是否能提升需要看实际情况,多读少写的情况,读写锁更有期望能较好的提升性能表现,否则,可能不如用普通自旋锁,因为读写锁对写操作其实是不太友好的,需要等全部读完了才能再写。

其他方面和普通自旋锁相似,比如

获取不到锁时,也是忙等的;

对临界区要求也不能执行会引发调度的代码,如睡眠,等待事件,文件系统操作等;

有中断上下文访问读写锁保护的临界区,线程上下文也要使用带中断保护的版本,原理相似。

常用接口

头文件 <linux/rwlock.h>

以下是一些常用的读写锁(rwlock)的 API 接口函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//初始化读写锁对象。
void rwlock_init(rwlock_t *lock)

//获取读锁,允许多个线程同时持有读锁。
void read_lock(rwlock_t *lock)
void read_lock_bh(rwlock_t *lock)
void read_lock_irqsave(rwlock_t *lock, unsigned long flags)

//释放读锁。
void read_unlock(rwlock_t *lock)
void read_unlock_bh(rwlock_t *lock)
void read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)

//获取写锁,独占地进行写操作。
void write_lock(rwlock_t *lock)
void write_lock_bh(rwlock_t *lock)
void write_lock_irqsave(rwlock_t *lock, unsigned long flags)

//释放写锁。
void write_unlock(rwlock_t *lock)
void write_unlock_bh(rwlock_t *lock)
void write_unlock_irqrestore(rwlock_t *lock, unsigned long flags)


//尝试获取读锁,如果锁可用则立即返回 1,否则返回 0。
int read_trylock(rwlock_t *lock)
//尝试获取写锁,如果锁可用则立即返回 1,否则返回 0。
int write_trylock(rwlock_t *lock)

以上是常用读写自旋锁的接口,还有一点需要注意,就是获取了读锁后,用户在临界段中应该只能对共享资源进行读操作,不能做写操作,否则,用这个读写锁就 没有意义了。获取写锁应该还好,毕竟写锁是独占访问的。

This post is licensed under CC BY 4.0 by the author.

平台总线及设备和驱动

内核-semaphore(信号量)