自旋锁--Test and Set Clock机制分析

自旋锁–Test and Set Clock机制分析

@(OS)

自旋锁:为防止多处理器并发引入的一种锁。

在内核中,广泛应用于中断处理部分。而在单处理器中,防止中断处理处理中的并发简单采用关闭中断即可,在PSW中打开/关闭中断标志位,用不到自旋锁。反之,用了自旋锁机制,就不用再管开中断或者关中断

自旋锁的设计初衷是忙则等待

理解

目的:为了实现保护共享资源,任何时刻只能有一个保持者。即只有一个进程可以获得锁。

自旋锁机制下,如果自旋锁已经被别的执行单元保持,那么调用者就一直循环在那里看自旋锁的保持者是否释放了锁,即忙则等待。很多出题点喜欢在这个概念上混淆,故意出成让权等待。让全等待是出让CPU,这里没有体现这个思路。因为跟CPU无关。自旋是个很形象的动作,表示一直在原地运动,并未去睡眠。这是区别于互斥锁的。

互斥锁机制下,如果资源被占用,资源申请者就会进入睡眠状态

原理的理解

  • 执行单元想访问被自旋锁保护的共享资源,必须先获得锁。
  • 访问完共享资源后,必须释放锁。

当准备去获取自旋锁时,发现锁没人在用,顺利获得锁,可以访问共享资源。否则,就一直在等。这就像在火车上用卫生间,如果空闲,就可以马上进去,且把门锁上,保护隐私。用完了把门打开走掉。如果里面有人,只好在外面等,如果着急,你肯定会一直等着,在那着急自旋。这就是自旋锁机制。如果你不等了,回座位休息去,那就是互斥锁机制。

自旋锁是比较低级的保护数据结构,贴近硬件层面实现。

可能存在的问题:

  • 死锁
  • 过多占用CPU资源

推导出自旋锁适合使用者保持锁时间较短的情况。

而信号量机制适合保持锁较长时间,因此没有资源可用时去睡眠。

实现

多处理机互斥算法:

do
{
    ...
    while(Test_And_Set_Lock(&lock)); //特别注意分号,以及传递的参数是引用参数
    //临界区
    lock = False;
    //剩余区
}while(True)

Test_And_Set_Lock函数是用硬件保持的原子运行,不被打断。

特别注意while(Test_And_Set_Lock(&lock));这句后面是个分号就是说会循环等待解锁。

理解到这个地步,就可以来思考一道真题了。

(2016.27)使用TSL指令实现进程互斥的伪代码如下:

do
{
    ...
    while(Test_And_Set_Lock(&lock)); //特别注意分号,以及传递的参数是引用参数
    //临界区
    lock = False;
    //剩余区
}while(True)

下列与该实现机制相关的叙述中,正确的是:
A. 退出临界区的进程负责唤醒阻塞态进程
B. 等待进入临界区的进程不会主动放弃CPU
C. 上述伪代码满足“让权等待”的同步准则
D. while(Test_And_Set_Lock(&lock))语句应在关中断状态下执行

分析:由上面的一大段分析可知,A项表述的是信号量机制这些进程较长时才有的状态,即进程无法访问临界资源时要去睡眠,在TSL里,都是短进程,都是精力充沛的,忙则等待的类型。因此,没人睡,自然也不存在唤醒。
C项让权等待与B项表达的东西是相反的。让权是什么意思?有必要特别说明。让权等待是一种策略,但是对象可以是CPU也可以是临界资源。这要看具体语境。这里,针对临界资源的访问,让权等待是指:当进程不能进入临界区时,应立即释放处理器,防止进程忙等待。我们需要形成一种概念是,进程是程序的动态执行过程,忙则等待资源时,必然是在运行的进程,是有CPU在背后力挺的,睡眠就是说没有资源赶紧滚,别占着CPU!

想一想进程调度的三大基本形态:就绪态,运行态,阻塞态三态之间的互相转化。

因此,C项错,B项对,忙则等待就是要占着CPU,所幸的是进程不长,否则递归调用一定产生死锁。

D项是很细致的考察,前面专门提过,TSL是多处理器下的进程并发问题,只有在中断机制下采用PSW,关中断/开中断方式来进行进程的并发控制。

你可能感兴趣的:(操作系统)