自旋锁

转载 2012年03月30日 09:42:01

在初级驱动的我们介绍了几种同步方式,有同学对自旋锁有些不理解,现在把这部分内容详细的讲述一下。

自旋锁与互斥锁有点类似,只是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,"自旋"一词就是因此而得名。由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而不是睡眠是非常必要的,自旋锁的效率远高于互斥锁。

信号量和读写信号量适合于保持时间较长的情况,它们会导致调用者睡眠,因此只能在进程上下文使用(_trylock的变种能够在中断上下文使用),而自旋锁适合于保持时间非常短的情况,它可以在任何上下文使用。如果被保护的共享资源只在进程上下文访问,使用信号量保护该共享资源非常合适,如果对共巷资源的访问时间非常短,自旋锁也可以。但是如果被保护的共享资源需要在中断上下文访问(包括底半部即中断处理句柄和顶半部即软中断),就必须使用自旋锁。

自旋锁保持期间是抢占失效的,而信号量和读写信号量保持期间是可以被抢占的。自旋锁只有在内核可抢占或SMP的情况下才真正需要,在单CPU且不可抢占的内核下,自旋锁的所有操作都是空操作。

跟互斥锁一样,一个执行单元要想访问被自旋锁保护的共享资源,必须先得到锁,在访问完共享资源后,必须释放锁。如果在获取自旋锁时,没有任何执行单元保持该锁,那么将立即得到锁;如果在获取自旋锁时锁已经有保持者,那么获取锁操作将自旋在那里,直到该自旋锁的保持者释放了锁。

无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。

自旋锁的API有(以下翻译自《LDDv2》英文版):

spin_lock_init(x)
        该宏用于初始化自旋锁x。自旋锁在真正使用前必须先初始化。该宏用于动态初始化。

DEFINE_SPINLOCK(x)
        该宏声明一个自旋锁x并初始化它。该宏在2.6.11中第一次被定义,在先前的内核中并没有该宏。

SPIN_LOCK_UNLOCKED
        该宏用于静态初始化一个自旋锁。

DEFINE_SPINLOCK(x)等同于spinlock_t x = SPIN_LOCK_UNLOCKEDspin_is_locked(x)
        该宏用于判断自旋锁x是否已经被某执行单元保持(即被锁),如果是,返回真,否则返回假。

spin_unlock_wait(x)
        该宏用于等待自旋锁x变得没有被任何执行单元保持,如果没有任何执行单元保持该自旋锁,该宏立即返回,否则将循环在那里,直到该自旋锁被保持者释放。

spin_trylock(lock)
        该宏尽力获得自旋锁lock,如果能立即获得锁,它获得锁并返回真,否则不能立即获得锁,立即返回假。它不会自旋等待lock被释放。

spin_lock(lock)
        该宏用于获得自旋锁lock,如果能够立即获得锁,它就马上返回,否则,它将自旋在那里,直到该自旋锁的保持者释放,这时,它获得锁并返回。总之,只有它获得锁才返回。

spin_lock_irqsave(lock, flags)
         该宏获得自旋锁的同时把标志寄存器的值保存到变量flags中并失效本地中断。

spin_lock_irq(lock)
         该宏类似于spin_lock_irqsave,只是该宏不保存标志寄存器的值。

spin_lock_bh(lock)
         该宏在得到自旋锁的同时失效本地软中断。

spin_unlock(lock)
         该宏释放自旋锁lock,它与spin_trylock或spin_lock配对使用。如果spin_trylock返回假,表明没有获得自旋锁,因此不必使用spin_unlock释放。

spin_unlock_irqrestore(lock, flags)
         该宏释放自旋锁lock的同时,也恢复标志寄存器的值为变量flags保存的值。它与spin_lock_irqsave配对使用。

spin_unlock_irq(lock)
         该宏释放自旋锁lock的同时,也使能本地中断。它与spin_lock_irq配对应用。

spin_unlock_bh(lock)
         该宏释放自旋锁lock的同时,也使能本地的软中断。它与spin_lock_bh配对使用。

spin_trylock_irqsave(lock, flags)
        该宏如果获得自旋锁lock,它也将保存标志寄存器的值到变量flags中,并且失效本地中断,如果没有获得锁,它什么也不做。因此如果能够立即获得锁,它等同于spin_lock_irqsave,如果不能获得锁,它等同于spin_trylock。如果该宏获得自旋锁lock,那需要使用spin_unlock_irqrestore来释放。

spin_trylock_irq(lock)
         该宏类似于spin_trylock_irqsave,只是该宏不保存标志寄存器。如果该宏获得自旋锁lock,需要使用spin_unlock_irq来释放。

spin_trylock_bh(lock)
        该宏如果获得了自旋锁,它也将失效本地软中断。如果得不到锁,它什么也不做。因此,如果得到了锁,它等同于spin_lock_bh,如果得不到锁,它等同于spin_trylock。如果该宏得到了自旋锁,需要使用spin_unlock_bh来释放。

spin_can_lock(lock)
        该宏用于判断自旋锁lock是否能够被锁,它实际是spin_is_locked取反。如果lock没有被锁,它返回真,否则,返回假。该宏在2.6.11中第一次被定义,在先前的内核中并没有该宏。

自旋锁(spinlock) 解释得经典,透彻

http://blog.csdn.net/unbutun/article/details/5730037 自旋锁与互斥锁有点类似,只是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,...
  • jeffasd
  • jeffasd
  • 2016年05月05日 12:02
  • 8096

linux多线程之自旋锁

基本概念: 何谓自旋锁?它是为实现保护共享资源而提出一种锁机制。其实,自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,...
  • daiyudong2020
  • daiyudong2020
  • 2016年08月14日 00:17
  • 1152

聊聊高并发(六)实现几种自旋锁(一)

在聊聊高并发(五)理解缓存一致性协议以及对并发编程的影响 我们了解了处理器缓存一致性协议的原理,并且提到了它对并发编程的影响,“多个线程对同一个变量一直使用CAS操作,那么会有大量修改操作,从而产生大...
  • ITer_ZC
  • ITer_ZC
  • 2014年10月22日 11:39
  • 6127

自旋锁公平性的三种实现代码下载

  • 2017年07月17日 00:29
  • 3KB
  • 下载

linux 自旋锁讨论记录

  • 2010年08月06日 21:40
  • 449KB
  • 下载

SQL server 自旋锁争用专题

  • 2014年12月01日 12:54
  • 538KB
  • 下载

嵌入式开发教程之Linux 内核的排队自旋锁--千锋教育

  • 2011年06月14日 19:32
  • 177KB
  • 下载

Java轻量级锁(自旋锁)和偏向锁原理

  • 2013年10月13日 10:10
  • 695KB
  • 下载

DirectShow采集音频,采用环形缓冲区对象将音频数据提供出来,还提供了自旋锁的概念

  • 2017年05月08日 21:59
  • 2.59MB
  • 下载

Windows驱动编程视频教程 提升IRQ与自旋锁

  • 2010年08月19日 21:51
  • 3.77MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:自旋锁
举报原因:
原因补充:

(最多只允许输入30个字)