自旋锁/Spin lock
Contents
自旋锁/Spin lock
|
|
自旋锁是为实现保护共享资源而提出一种锁机制。其实,自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。但是两者在调度机制上略有不同。对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,“自旋"一词就是因此而得名。
自旋锁适用于锁保护的临界区很小的情况,临界区很小的话,锁占用的时间就很短。
自旋锁一般原理
跟互斥锁一样,一个执行单元要想访问被自旋锁保护的共享资源,必须先得到锁,在访问完共享资源后,必须释放锁。如果在获取自旋锁时,没有任何执行单元保持该锁,那么将立即得到锁;如果在获取自旋锁时锁已经有保持者,那么获取锁操作将自旋在那里,直到该自旋锁的保持者释放了锁。由此我们可以看出,自旋锁是一种比较低级的保护数据结构或代码片段的原始方式,这种锁可能存在两个问题: 死锁和过多占用cpu资源。
自旋锁适用情况
自旋锁比较适用于锁使用者保持锁时间比较短的情况。正是由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而不是睡眠是非常必要的,自旋锁的效率远高于互斥锁。信号量和读写信号量适合于保持时间较长的情况,它们会导致调用者睡眠,因此只能在进程上下文使用,而自旋锁适合于保持时间非常短的情况,它可以在任何上下文使用。如果被保护的共享资源只在进程上下文访问,使用信号量保护该共享资源非常合适,如果对共享资源的访问时间非常短,自旋锁也可以。但是如果被保护的共享资源需要在中断上下文访问 (包括底半部即中断处理句柄和顶半部即软中断) ,就必须使用自旋锁。自旋锁保持期间是抢占失效的,而信号量和读写信号量保持期间是可以被抢占的。自旋锁只有在内核可抢占或SMP (多处理器) 的情况下才真正需要,在单CPU且不可抢占的内核下,自旋锁的所有操作都是空操作。另外格外注意一点: 自旋锁不能递归使用。
缺点
CAS操作需要硬件的配合;
保证各个CPU的缓存 (L1、L2、L3、跨CPU Socket、主存) 的数据一致性,通讯开销很大,在多处理器系统上更严重;
没法保证公平性,不保证等待进程/线程按照FIFO顺序获得锁。
自旋锁是最简单的一种阻塞线程的办法,就是在一个死循环里不断检查等待的条件是否满足,直至满足之后才跳出循环。很显然,自旋锁的最大缺点是白白消耗计算资源,并且把调度的责任完全交给了线程调度器。但是自旋锁最大的优点就是减少线程切换的次数。因为线程切换需要CPU从用户态进入核心态,是非常昂贵的操作。特别是在等待时间较短时,频繁地切换线程的运行状态可能得不偿失。
http://www.cnblogs.com/biyeymyhjob/archive/2012/07/21/2602015.html
http://ifeve.com/java_lock_see1
http://ifeve.com/java_lock_see1/embed/#?secret=0zgZ1kp03E
https://coderbee.net/index.php/concurrent/20131115/577
https://coderbee.net/index.php/concurrent/20131115/577/embed#?secret=DLJab8XJP7
Author -
LastMod 2017-05-04