一、概念简介
1、自旋锁
自旋锁是专门为防止多处理器并发而引入的一种锁,主要用于对称多处理器(SMP)环境中,在内核中大量用于中断处理等部分。自旋锁最多只能被一个内核任务持有,若一个内核任务试图请求一个已被争用的自旋锁,那么这个任务就会一直进行忙循环——>旋转——>等待锁重新可用。若锁未被争用,请求它的内核任务便能立刻得到它并且继续执行。自旋锁可以在任何时刻防止多于一个的内核任务同时进入临界区,因此这种锁可有效地避免多处理器上并发运行的内核任务竞争共享资源。
自旋锁基本形式如下:
spin_lock(&mr_lock)
/*临界区*/
spin_unlock(&mr_lock)
简而言之,自旋锁在内核中主要用来防止多处理器中并发访问临界区,防止内核抢占造成的竞争。自旋锁不允许任务睡眠,它能够在中断上下文中使用。
自死锁:自己占有了某个资源,然后自己又申请这个已占有的资源,这显然不可能再获得该资源了,因此会出现“自缚手脚”。
注意:自旋锁一定是由系统内核调用的,不可能在用户程序中由用户请求自旋锁。
2、信号量
linux中的信号量是一种睡眠锁。如果有一个任务试图获得一个已经被持有的信号量时,信号量会将其推入等待队列,然后让其睡眠,这时处理器获得自由去执行其它代码。当持有信号量的进程将信号量释放后,在等待队列中的一个任务被唤醒,从而可以获得此信号量。
二、对比分析
1、二者区别
自旋锁不会引起调用者睡眠,如果自旋锁已被别的执行单元保持,调用者就一直循环查看该自旋锁的保持者是否已释放了锁。
信号量会引起调用者睡眠,它会把进程从运行队列上拖出去让其睡眠,除非获得锁。
2、使用场景
具体的使用场景主要取决于锁被持有的时间长短,理想的情况下是所有的锁都应该尽可能短的被持有,如果锁被持有的时间较长的话,使用信号量较好。此外,信号量不同于自旋锁,它不会关闭内核抢占,所以持有信号量的代码可以被抢占。
不同需求对应的建议加锁方法如下表:
需求 | 建议的加锁方法 |
低开销加锁 | 优先使用自旋锁 |
短期锁定 | 优先使用自旋锁 |
中断上下文加锁 | 使用自旋锁 |
长期加锁 | 优先使用信号量 |
持有锁时需要睡眠 | 使用信号量 |
-------------------------------------------------------The end-------------------------------------------------