自旋锁

1. 定义

一个自旋锁是一个互斥设备,它只能有两个值:“锁定”和“解锁”。如果锁可用,则“锁定”位被设置,而代码继续进入临界区;相反,如果锁被其他人获得,则代码进入忙循环并重复检查这个锁,直到该锁可用为止。这个循环为“自旋”

2. 实现

             "\n1:\t"  
             lock " ; decb %0\n\t"  
             "jns 3f\n"  
             "2:\t"  
             "rep;nop\n\t"  
             "cmpb $0,%0\n\t"  
             "jle 2b\n\t"  
             "jmp 1b\n"  
             "3:\n\t" 

    第2行:lock>slock自减一,前面的lock保证原子操作

    第3行:如果lock>slock为非负数,跳转到3,获得锁

    第5行:lock->slock为负数,锁 被其他线程抢占,等待

    第6行:将lock->slock和0比较

    第7行:判断lock->slock是否小于等于0,如果判断为真,跳转到2,继续等待

    第8行:此时lock->slock已经大于0,跳转到1抢占锁

3. 各平台区别

自旋锁是为了多CPU而设计的,但单CPU抢占内核时也类似于SMP。但各种情况还有一些差别,下面分类讨论。

I. 单CPU非抢占:自旋锁空操作,完全剔除内核

II.单CPU抢占:禁止CPU抢占,无自旋锁

III.多CPU非抢占:自旋锁。

IV.多CPU抢占:禁止CPU抢占,有自旋锁。

问 :    在单CPU非抢占中,为什么自旋锁会实现为空操作?

多线程之间共享数据,无自旋锁会引起并发访问吗?

答 :    如果非抢占单CPU进入某个锁的自旋状态,则会永远自旋下去。(这句话要好好理解)

如果多线程在访问共享数据的时候不休眠或者主动放弃CPU(schedule),不会引起并发访问。因为没有进行进行线程切换,另外一个线程不会访问此共享数据。这里要说一下中断的时候,如果中断和此线程共享数据,要先禁用中断,才能防止并发访问。

4. 自旋锁函数

I. spin_trylock(spinlock_t *lock)

在使用此函数的时候一定要注意检查返回值,如果返回失败,而又去修改共享数据,还是会引起竞争。相当于没有获取到锁,破门而入。

II.spin_lock_irqsave(spinlock_t *lock, unsigned long flags) 和spin_lock_bh(spinlock_t *lock)

进程上下文与下半部或中断共享数据。进程上下文会被softirq 或irq中断,如果没有禁用下半部或中断,在此进程上下文获得锁的情况下,此进程被中断,而中断又去取锁,会引起死锁

 


你可能感兴趣的:(自旋锁)