📅  最后修改于: 2020-12-14 03:38:02             🧑  作者: Mango
在锁变量机制中,有时Process会读取锁变量的旧值并进入关键部分。由于这个原因,关键部分可能会涉及多个过程。但是,下一节第一部分中显示的代码可以替换为第二部分中显示的代码。这不会影响算法,但是通过这样做,我们可以设法在某种程度上但并非完全提供互斥。
在更新的代码版本中,将Lock的值加载到本地寄存器R0中,然后将lock的值设置为1。
但是,在第3步中,将锁的先前值(现在已存储到R0中)与0进行比较。如果该值为0,则该过程将简单地进入临界区,否则将通过在循环中连续执行来等待。
通过进程本身将锁立即设置为1的好处是,现在进入关键部分的进程将携带锁变量的更新值1。
在被抢占和再次调度的情况下,无论锁变量的当前值如何,它都不会进入临界区,因为它已经知道锁变量的更新值是什么。
Section 1 | Section 2 |
---|---|
1. Load Lock, R0 2. CMP R0, #0 3. JNZ step1 4. store #1, Lock |
1. Load Lock, R0 2. Store #1, Lock 3. CMP R0, #0 4. JNZ step 1 |
但是,以上部分中提供的解决方案在一定程度上提供了互斥,但并不能确保互斥将始终存在。关键部分可能有多个过程。
如果在执行第2节中编写的汇编代码的第一条指令后立即抢占了该进程怎么办?在这种情况下,它将携带锁变量的旧值,并且无论知道锁变量的当前值如何,都会进入临界区。这可能会使这两个过程同时出现在关键部分中。
为了摆脱这个问题,我们必须确保在加载前一个锁变量值之后并且将其设置为1之前,不要发生抢占。如果能够合并前两个,就可以解决问题。说明。
为了解决该问题,操作系统提供了一条称为“测试集锁定”(TSL)指令的特殊指令,该指令仅将锁定变量的值加载到本地寄存器R0中并同时将其设置为1。
首先执行TSL的流程将进入关键部分,此后没有其他流程可以进入第一个流程。即使抢占了第一个进程,也没有任何进程可以执行关键部分。
解决方案的汇编代码如下所示。
让我们根据这四个条件检查TSL。
在TSL机制中保证了互斥,因为永远不会在设置锁变量之前抢占一个进程。在特定时间只有一个进程可以将lock变量视为0,这就是为什么可以保证互斥的原因。
根据进度的定义,不想进入关键部分的流程不应阻止其他流程进入。在TSL机制中,仅当进程想要进入关键部分时才执行TSL指令。如果没有进程不想进入关键部分,则锁的值将始终为0,因此在TSL中始终保证进度。
TSL中不能保证有界等待。某些过程可能没有那么久的机会。我们无法预测某个过程一定会在一定时间后进入关键部分。
TSL不提供架构中立性。这取决于硬件平台。 TSL指令由操作系统提供。某些平台可能不提供该功能。因此,这不是建筑上的自然现象。