您的位置:首页 > 其它

spinlock mutex semaphore rwlock

2011-04-22 09:49 323 查看
spinlock mutex语义上是一样的,都是对一临界区加锁保护,
区别是mutex得不到锁会睡眠,因此不能在中断上下文中使用。
另外,解锁的一定是上锁的那个 semaphore 得不到锁会睡眠,也不能用在中断中, 上锁的不一定负责解锁 。
rwlock 很好理解了,可多个读,只有一个写者,同样会引起睡眠
最重要的就是只有spinlock 可以用在中断上下文中.

至于wait_queue,不是同步手段,是内核管理sleeping进程的一种手段
什么是等待队列?
在软件开发中任务经常由于某种条件没有得到满足而不得不进入睡眠状态,然后等待条件得到满足的时候再继续运行,进入运行状态。这种需求需要等待队列机制的支持。
而且semaphore(我不知道所有的实现是不是这样)中也用到了wait_queue_head
-----------------------------------------
spinlock和信号量sem的区别
重点:死循环/睡眠
spinlock只是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁。sem则会导致调用睡眠。然后应用上就是前者可以在中断处理中使用,后者不行。
信号量是针对使用时间比较长的共享资源,而自旋锁的则一般时间较短.一般的申请锁被其它保存则循环不止的等待.

* Spinlock 不断的检查等待的对象是否就绪,该进程/LWP始终处于Running的状态
* Sem使该进程/LWP进入Wait转台,系统会将CPU切换给其他的进程/LWP运行。

由于这个根本特性的不同,导致了以下用法上的不同:

1. Spinlock 只适用于短暂的等待,因为没有进程切换所以对于短暂等待他的效率会比较高。 但是对于长时间等待,由于它的CPU占用是100% 等的越长越不合算。

2. Spinlock只能在多个CPU的系统上用,因为等待者占据了100%的CPU,只由另外一个CPU上的进程才能解锁。

两者都是用于Linux内核互斥。避免并发,防止竞争,对系统公共资源或者共有数据进行合理保护的。Spin Lock的出现是因为Symmetric Multi-Processor的出现,如果是UniProcessor,用简单的Disable IRQ就可以满足其要求。Spin Lock是通过Poll方式的,其可以说是一个Test and Set or Test and Clear的模型的延伸。而Semaphore则是传统的IPC,是通过Sleep and Wake up方式实现的。通过Spin Lock and Semaphore两者的实现机制则,我们可以_很明晰的_看出两者的应用场合。
(在高并发的地方,轮询比睡眠更高效)

Semaphore是一件可以容纳N人的房间,如果人不满就可以进去,如果人满了,就要等待有人出来。对于N=1的情况,称为binary semaphore。一般的用法是,用于限制对于某一资源的同时访问。

Binary semaphore与Mutex的差异:

在有的系统中Binary semaphore与Mutex是没有差异的。在有的系统上,主要的差异是mutex一定要由获得锁的进程来释放。而semaphore可以由其它进程释 放(这时的semaphore实际就是个原子的变量,大家可以加或减),因此semaphore可以用于进程间同步。Semaphore的同步功能是所有 系统都支持的,而Mutex能否由其他进程释放则未定,因此建议mutex只用于保护critical section。而semaphore则用于保护某变量,或者同步。

另一个概念是spin lock,这是一个内核态概念。spin lock与semaphore的主要区别是spin lock是busy waiting,而semaphore是sleep。对于可以sleep的进程来说,busy waiting当然没有意义。对于单CPU的系统,busy waiting当然更没意义(没有CPU可以释放锁)。因此,只有多CPU的内核态非进程空间,才会用到spin lock。Linux kernel的spin lock在非SMP的情况下,只是关irq,没有别的操作,用于确保该段程序的运行不会被打断。其实也就是类似mutex的作用,串行化对 critical section的访问。但是mutex不能保护中断的打断,也不能在中断处理程序中被调用。而spin lock也一般没有必要用于可以sleep的进程空间。

spinlock是多CPU下的同步机制,在获取锁时,如果失败,它不会挂起当前的执行过程。与之相对的,mutex和semaphore等同步机制,如果获取mutex或semaphore失败,它会挂起当前的执行过程,而在mutex或semaphore退出是,唤醒相应的过程。
不同的同步机制,是为了解决不同的问题。在单cpu上,不可能有spinlock,因为当前只能有一个活动的执行路径。而mutex或者semaphore则可以挂起当前的线程或者进程,CPU这时可以做其他的事情,等到挂在mutex或者semaphore上的进程被唤醒时,再继续执行被挂起的路径。
可以想象,spinlock的设计并不是不能支持挂起当前执行过程的操作。只是,在内核中,挂起当前的执行过程,就必须先能够标识这个过程。内核线程,或者进程,都有相应的结构;但是,哪些不属于这两种的执行过程,就必须使用spinlock。还有,如果一组进程在执行过程中,要求必须是同步执行,不能被打断,这种情况下spinlock也是必须的。
说了这么多,主要的意思就是说,不能的同步机制适用于不同的场景,解决不同的问题。没有一种同步机制可以解决所有的问题,这也是为什么linux里面不断有新的同步机制被引入内核。当新的问题出现时,现有的机制不能解决,或者不能很好解决这个问题时,就有必要引入新的机制来解决这个问题。
锁是一种协议,是有共享临界区的执行过程之间达成的协议。有了api,并不能保证程序的正确,还需要正确的,合理的使用api。尤其是在多cpu情况下,锁的使用,对性能有很大的影响。最好的办法就是不使用锁,每个CPU都是完全独立的运行。这也要看具体的应用,如果数据之间没有关联,当然可以独立地去处理;反之,则必须要锁来保护。
比如用multicore实现网络包的转发时,当然可以把某个流绑定到某个CPU上,假设流与流直接是完全独立的,这种情况下,每个CPU都可以独立的处理属于自己的流,不需要和其他CPU共享数据。但是,由于不同的流,流量是不同的,这样,CPU的能力没有被充分的利用,资源的使用也不平衡。这样的设计并不能很好的解决问题。
选择哪种设计方案,要综合的去考虑,没有最完美的解决方案,因为很多需求是相互冲突的,一个折衷的方案就是最后的选择。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: