前言
前面我们讲到定时器的使用,本篇讲下自旋锁的使用。想第一时间看我的文章的话可以点击公众号主页右上角有个设为星标,以免错过好文。本文源码采用Linux内核5.10
自旋锁简介
自旋锁是Linux内核里最常用的锁之一,自旋锁的概念很简单,就是如果加锁失败在等锁时候是使用休眠等待还是忙等待,如果是忙等待的话,就是自旋锁,这也是自旋锁名字的由来。如果是休眠等待的锁那就是互斥锁另外一个场景,下篇再讲互斥锁。自旋锁的效率远高于互斥锁
举个例子: 当一个线程要访问某个共享资源的时候首先要先获取相应的锁,锁只能被一个线程持有,只要次线程不释放持有的锁,那么其他的线程就不能获取此锁。对于自旋锁而言,如果自旋锁正在被线程A持有,线程B想要获取自旋锁,那么线程B想要获取自旋锁,那么线程B就会处于忙循环-旋转-等待状态,线程B不会进入休眠状态或者说去做其他的处理,而是会一直傻傻的在那里转圈圈原地打转锁可用。就比如现在有个公共电话亭,一次肯定只能进去一个人打电话,现在电话亭里面有人正在打电话,相当于获取自旋锁。此时你到了电话亭门口,因为里面有人,所以你不能进去打电话,相当于没有获取了自旋锁。此时你到了电话亭门口,因为里面有人,所以你不能进去打电话,相当于没有获取自旋锁,这时候你原地等待,你可能因为无聊的等待而转圈圈消磨时光,反正就是哪里也不能去,要一直等到里面的人打完电话出来。终于,里面的人打完电话出来了,相当于释放了自旋锁,这个时候你就可以使用电话亭打电话了,就相当于获取到了自旋锁。
注意: 等待自旋锁的线程会一直处于自旋状态,这样会浪费处理器时间,降低系统性能,所以自旋锁持有时间不能太长。所以自旋锁适用于短时期的轻量级加锁,如果遇到需要长时间持有锁的场景那就不适合用自旋锁,就像一个人在ATM里待了一天,其他人没法办业务
自旋锁的数据结构
Linux内核使用结构体spinlock_t表示自旋锁,结构体定义如下所示:
file:include/linux/spinlock_types.h
typedef struct spinlock{
union{
struct raw_spinlock rlock;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
#define LOCK_PADSIZE (offsetof(struct raw_spinlock, dep_m