自旋锁和信号量区别

在驱动程序中,当多个线程同时访问相同的资源时(驱动程序中的全局变量是一种典型的共享资源),可能会引发"竞态",因此我们必须对共享资源进行并发控制。Linux内核中解决并发控制的最常用方法是自旋锁与信号量(绝大多数时候作为互斥锁使用)。

  自旋锁与信号量"类似而不类",类似说的是它们功能上的相似性,"不类"指代它们在本质和实现机理上完全不一样,不属于一类。

  自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环查看是否该自旋锁的保持者已经释放了锁,"自旋"就是"在原地打转"而信号量则引起调用者睡眠,它把进程从运行队列上拖出去,除非获得锁。这就是它们的"不类"。

  但是,无论是信号量,还是自旋锁,在任何时刻,最多只能有一个保持者,即在任何时刻最多只能有一个执行单元获得锁。这就是它们的"类似"。

  鉴于自旋锁与信号量的上述特点,一般而言,自旋锁适合于保持时间非常短的情况,它可以在任何上下文使用;信号量适合于保持时间较长的情况,会只能在进程上下文使用。如果被保护的共享资源只在进程上下文访问,则可以以信号量来保护该共享资源,如果对共享资源的访问时间非常短,自旋锁也是好的选择。但是,如 果被保护的共享资源需要在中断上下文访问(包括底半部即中断处理句柄和顶半部即软中断),就必须使用自旋锁。

区别总结如下:
   1、由于争用信号量的进程在等待锁重新变为可用时会睡眠,所以信号量适用于锁会被长时间持有的情况。
   2、相反,锁被短时间持有时,使用信号量就不太适宜了,因为睡眠引起的耗时可能比锁被占用的全部时间还要长。
   3、由于执行线程在锁被争用时会睡眠,所以只能在进程上下文中才能获取信号量锁,因为在中断上下文中(使用自旋锁)是不能进行调度的。
   4、你可以在持有信号量时去睡眠(当然你也可能并不需要睡眠),因为当其它进程试图获得同一信号量时不会因此而死锁,(因为该进程也只是去睡眠而已,而你最终会继续执行的)。
   5、在你占用信号量的同时不能占用自旋锁,因为在你等待信号量时可能会睡眠,而在持有自旋锁时是不允许睡眠的。
   6、信号量锁保护的临界区可包含可能引起阻塞的代码,而自旋锁则绝对要避免用来保护包含这样代码的临界区,因为阻塞意味着要进行进程的切换,如果进程被切换出去后,另一进程企图获取本自旋锁,死锁就会发生。
   7、信号量不同于自旋锁,它不会禁止内核抢占(自旋锁被持有时,内核不能被抢占),所以持有信号量的代码可以被抢占,这意味着信号量不会对调度的等待时间带来负面影响。
  除了以上介绍的同步机制方法以外,还有BKL(大内核锁),Seq锁等。
  BKL是一个全局自旋锁,使用它主要是为了方便实现从Linux最初的SMP过度到细粒度加锁机制。
  Seq锁用于读写共享数据,实现这样锁只要依靠一个序列计数器。

个人理解:

信号量(进程间的通信机制(单一个数的信号),与消息邮箱,消息队列,机理类同,量不同,)用信号量肯定掉cpu;

自旋锁:保护区域不掉cpu,持续查找,等待(不可用时域长状态);

切记: 时域范围: 在进程间的通信机制函数状态 ∩ 锁 = 0;

/* end */

原文地址:https://www.cnblogs.com/Ph-one/p/6101290.html