各种同步锁的区别

转载 2015年11月19日 15:06:28

这两天经常有同事在问spinlock和semaphore的相关问题,什么时候该用spinlock?什么时候该用semaphore?什么时候该用spinlock_irq?什么时候该用spinlock_irqsave?的确,对于初涉内核开发的人员来说,spinlock和semaphore的应用是一个比较大的疑问。这里,我来谈谈我对这两个概念的想法吧。

Spinlock的实现机制可以描述如下:CPU首先将内存总线lock住,然后检测内存中的lock数据,如果数据为真,那么表示资源被人占用,无法获取。然后CPU会自璇检测该lock数据,直到数据不为真之后,lock该数据返回。在Linux中spinlock核心代码采用汇编语言实现,可以参考__raw_spin_lock函数。在2.6.25版本之后,Linux为了解决在多CPU平台上的不公平竞争,引入了排队自璇锁的算法。

说到这里,需要讲一下的是,spinlock在up平台上为空函数的说法。这个说法不是很严格,实际上在非强占的up平台上,spinlock的实现为空函数,在可抢占的up平台上,spinlock需要将抢占给disable掉,也就是说在spinlock的临界区,Linux无法抢占。在多CPU平台上,spinlock是有效的。

Semaphore的实现机制可以描述如下:CPU首先会检测信号量是否可获取,如果无法获取该信号量,那么就会导致一次上下文调度操作。从实现机制上来看,semaphore操作效率比较低,而spinlock的效率相对较高,但是这种效率的高低与应用相关,如果临界区操作的时间过长,那么采用spinlock会浪费大量的CPU时间,还不如做几次上下文调度释放CPU资源呢。所以,spinlock的应用有一个原则,那就是临界区操作尽可能的短,让CPU不要自璇太多的时间,这一点从spinlock的实现代码上也可以看出一些端倪,Linux开发人员着这个地方花费了好多心计。


从上面的机制描述,我想可以总结出如下几点:

1、  不允许睡眠的上下文需要采用spinlock,可以睡眠的上下文可以采用semaphore。在中断上下文中访问的竞争资源一定采用spinlock。

2、  临界区操作较长的应用建议采用semaphore,临界区很短的操作建议采用spinlock。

3、  需要关中断的场合需要调用spinlock_irq或者spinlock_irqsave,不明确当前中断状态的地方需要调用spinlock_irqsave,否则调用spinlock_irq。一个资源既在中断上下文中访问,又在用户上下文中访问,那么需要关中断,如果仅仅在用户上下文中被访问,那么无需关中断。


简单的说,自旋锁在内核中主要用来防止多处理器中并发访问临界区,防止内核抢占造成的竞争。另外自旋锁不允许任务睡眠(持有自旋锁的任务睡眠会造成自死锁——因为睡眠有可能造成持有锁的内核任务被重新调度,而再次申请自己已持有的锁),它能够在中断上下文中使用


Linux中的信号量是一种睡眠锁。如果有一个任务试图获得一个已被持有的信号量时,信号量会将其推入等待队列,然后让其睡眠。这时处理器获得自由去执行其它代码。当持有信号量的进程将信号量释放后,在等待队列中的一个任务将被唤醒,从而便可以获得这个信号量。
 

  信号量的睡眠特性,使得信号量适用于锁会被长时间持有的情况;只能在进程上下文中使用,因为中断上下文中是不能被调度的;另外当代码持有信号量时,不可以再持有自旋锁


自旋锁对信号量

需求 
                         建议的加锁方法


低开销加锁                      优先使用自旋锁
短期锁定                         优先使用自旋锁
长期加锁                         优先使用信号量
中断上下文中加锁         使用自旋锁
持有锁是需要睡眠、      调度    使用信号量


Mutex是一把钥匙,一个人拿了就可进入一个房间,出来的时候把钥匙交给队列的第一个。一般的用法是用于串行化对criticalsection代码的访问,保证这段代码不会被并行的运行。



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


四种进程或线程同步互斥的控制方法
1、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。 只能用来同步本进程内的线程,而不可用来同步多个进程中的线程
2、互斥量:为协调共同对一个共享资源的单独访问而设计的。 因为使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享
3、信号量:为控制一个具有有限数量用户资源而设计。 信号允许多个线程同时使用共享资源
4、事 件:用来通知线程有一些事件已发生,从而启动后继任务的开始。


进程间线程间的同步锁原理和种类

同步锁的基本概念: 锁基本都是内核对象,用于控制多线程间多进程间的同步访问。 我们知道进程间的同步操作都是要借助内核来完成的,和同一个进程中的线程同步只需要在用户模式下是有很大差别的,当然,对于进程安...
  • Blues1021
  • Blues1021
  • 2015年03月16日 23:47
  • 4382

多线程-锁的类型 && CAS 非阻塞同步

锁的类型 根据完成任务所需要的结构不同,一个应用程序可能会使用多种不同类型的锁原语,因此,开发人员必须避免在一个给定任务中混淆这些锁原语,尤其在使用第三方提供的库时需要格外小心。假设在一个应用程序中,...
  • xtzmm1215
  • xtzmm1215
  • 2015年08月05日 00:57
  • 2054

同步锁与异步锁的区别

异步锁:同一进程内的,多个线程间有互斥关系。只有等一个线程运行结束才能运行运行另一个进程。 同步锁:多个线程运行一个方法,因为方法上加了同了同步,一次只有一个线程运行,其他线程进入竞争进制。    同...
  • qq_35447305
  • qq_35447305
  • 2016年09月25日 18:39
  • 5824

线程同步(4):linux各种锁详解

在linux内核中,有很多同步机制。比较经典的有原子操作、spin_lock(忙等待的锁)、mutex(互斥锁)、semaphore(信号量)等。并且它们几乎都有对应的rw_XXX(读写锁),以便在能...
  • wentianyao
  • wentianyao
  • 2016年04月26日 15:24
  • 2054

java并发编程---synchronized和lock两种锁的比较

性能比较     在JDK1.5中,synchronized是性能低效的。因为这是一个重量级操作,它对性能最大的影响是阻塞的是实现,挂起线程和恢复线程的操作都需要转入内核态中完成,这些操作给系统的并...
  • u012470138
  • u012470138
  • 2016年12月06日 11:27
  • 2665

iOS 8种加锁 效率比较

iOS开发中常用的锁有如下几种 来比较一下遇到加锁的情况: 1. @synchronized 关键字加锁  2. NSLock 对象锁  3. NSCondition   4. NSConditio...
  • s3590024
  • s3590024
  • 2016年04月21日 10:42
  • 1697

linux 内核同步机制-自旋锁与信号量及其区别

这篇文章写得很不错!新人值得一看:http://www.360doc.com/content/12/0222/15/8555864_188631419.shtml 内核同步措施 ...
  • czc1009
  • czc1009
  • 2013年12月15日 19:48
  • 503

学习笔记 --- LINUX的同步互斥机制 --- 自旋锁与信号量的区别

所谓同步互斥就是说一个设备只能被一个应用程序打开,不能被两个应用程序同时访问,比如在PC机上只能用一个串口调试助手打开某个COM口,如果再打开一个调试助手,提示串口打开失败,只能先关闭先前打开的那个,...
  • shujis625972380
  • shujis625972380
  • 2014年03月09日 11:51
  • 656

lock Mutex Monitor 之间的区别与详解, .net 多线程 同步异步操作,锁

Framework为我们提供了三个加锁的机制,分别是Monitor类、Lock关 键字和Mutex类。   总体而言,lock和monitor可以锁定对象,也可以锁定函数;而mutex一般用...
  • xwdpepsi
  • xwdpepsi
  • 2012年10月02日 11:20
  • 3296

线程同步(互斥锁与信号量的作用与区别)

“信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在semtake的时候,就阻塞在 哪里)。而互斥锁是用在多线程多任务互斥的,一个线程占用...
  • tietao
  • tietao
  • 2012年03月19日 10:38
  • 34238
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:各种同步锁的区别
举报原因:
原因补充:

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