自旋锁,信号量和互斥锁

对于同步的方法,最基础的就是原子操作,他是其他同步方法的基石。原子操作可以保证指令以原子的方式去执行(执行过程不被打断)。但是,不可能每个临界区都可以用简单的原子操作。很多临界区尽可能跨越多个函数,简单的原子操作也无能为力,所以就需要更复杂的同步方法,锁来提供保护。

1. 自旋锁

自旋锁最多只能被一个线程所持有。如果一个执行线程试图获得一个被已经持有的自旋锁,那么该线程就会一直进行忙循环等待锁重新可用。也就是说自旋锁使得请求它的线程在等待重新可用的时候自旋(特别浪费处理器的时间)。这种行为是自旋锁的要点。所以自旋锁不应该被长时间持有。当然,还可以采取另一种方式去处理对锁的争用:让请求线程睡眠,直到锁重新可用的时候在唤醒。这样就不会一直占用cpu的时间,可以去执行其他代码。但是,这也会带来其他的开销。这里有明显的两次上下文切换(被阻塞的线程换出和换入)。因此,持有自旋的时间最好小于完成两次上下文消耗的时间。
另外,自旋锁可以使用在中断处理程序中。

2. 信号量

信号量是一种睡眠锁。如果一个任务试图获得一个不可用的信号量的时候,信号量会将其推进一个等待队列中,然后让其睡眠。这个时候,处理器可以去处理其他代码。当持有的信号量被释放后。处于队列中的任务被唤醒,并且或得该信号量。
所以说,信号量有至少两次的上下文切换,所以比自旋锁有更大的开销。但是,它可以更好的利用处理器。
另外,信号量可以同时允许任意数量的锁持有者,而自旋锁在一个时刻最多允许一个任务持有它。当信号量允许的使用数量是1的时候就是二值信号量。那么当计数是1的时候,说白了就是把他作为一个互斥的排他锁使用。但是信号量只做这个使用有些复杂(毕竟它更通用)。所以,就出现了互斥锁。

3. 互斥锁

互斥锁和使用计数是1的信号量类似,但是他的接口更加简单,实现也更加高效(这是因为信号量有更多的限制,更通用)。

那么什么时候用哪种锁呢?
当没有特殊要求的时候,信号量和互斥锁就选互斥锁。
那么互斥锁和自旋锁呢?
本质上就是在中断上下文中只能使用自旋锁,在任务睡眠时只能使用互斥锁。
长期加锁优先使用互斥锁。短期加锁优先使用自旋锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值