📜  硬件同步算法:解锁和锁定、测试和设置、交换

📅  最后修改于: 2021-09-28 11:05:05             🧑  作者: Mango

当两个并发运行的进程共享相同的数据或相同的变量时,就会出现进程同步问题。该变量的值在被第二个进程使用之前可能无法正确更新。这种条件被称为“绕行条件”。有针对此问题的软件和硬件解决方案。在本文中,我们将讨论处理同步问题的最有效硬件解决方案及其实现。

在解决进程同步问题的硬件方法中有三种算法:

  1. 测试和设置
  2. 交换
  3. 解锁和锁定

许多操作系统中的硬件指令有助于有效解决临界区问题。

1. 测试和设置:
这里,共享变量是 lock ,它被初始化为 false。 TestAndSet(lock) 算法以这种方式工作——它总是返回发送给它的任何值并将 lock 设置为 true。第一个进程将立即进入临界区,因为 TestAndSet(lock) 将返回 false 并退出 while 循环。其他进程现在无法进入,因为 lock 设置为 true,因此 while 循环继续为 true。确保相互排斥。一旦第一个进程离开临界区,lock 就会更改为 false。所以,现在其他进程可以一一进入了。进度也有保障。但是,在第一个进程之后,任何进程都可以进入。没有维护队列,因此任何发现锁再次为假的新进程都可以进入。因此不能确保有界等待。

测试和设置伪代码 –

//Shared variable lock initialized to false
boolean lock;

boolean TestAndSet (boolean &target){
    boolean rv = target;
    target = true;
    return rv;
}

while(1){
    while (TestAndSet(lock));
    critical section
    lock = false;
    remainder section
}
 

2. 交换:
交换算法很像 TestAndSet 算法。不是在 swap函数中直接将 lock 设置为 true ,而是将 key 设置为 true 然后与 lock 交换。因此,当一个进程处于临界区时,由于 lock 的值为真,没有其他进程可以进入它。确保相互排斥。同样,在临界区之外,lock 更改为 false,因此任何找到它的进程都不会进入临界区。进度有保障。然而,出于同样的原因,不能确保再次有界等待。

交换伪代码 –

// Shared variable lock initialized to false 
// and individual key initialized to false;

boolean lock;
Individual key;

void swap(booelan &a, boolean &b){
    boolean temp = a;
    a = b;
    b = temp;
}

while (1){
    key = true;
    while(key)
         swap(lock,key);
    critical section
    lock = false;
    remainder section
} 

3.解锁和锁定:
Unlock and Lock Algorithm 使用 TestAndSet 来调节 lock 的值,但它为每个进程添加另一个值 waiting[i],用于检查进程是否一直在等待。对于临界区中的进程,维护就绪队列。接下来进入的所有进程都根据它们的进程号添加到就绪队列中,不一定按顺序添加。一旦第 i 个进程离开临界区,它不会将 lock 变为 false 以便任何进程现在都可以使用临界区,这是以前算法的问题。相反,它检查队列中是否有任何进程在等待。该队列被认为是一个循环队列。 j 被认为是行中的下一个进程,while 循环检查从第 j 个进程到最后一个进程,并再次从 0 到第 (i-1) 个进程检查是否有任何进程等待访问临界区。如果没有进程在等待,则锁定值更改为 false,接下来的任何进程都可以进入临界区。如果存在,则该进程的等待值变为 false,从而使第一个 while 循环变为 false 并可以进入临界区。这确保了有限的等待。所以通过这个算法可以解决进程同步的问题。

解锁和锁定伪代码 –

// Shared variable lock initialized to false 
// and individual key initialized to false

boolean lock;
Individual key;
Individual waiting[i];

while(1){
    waiting[i] = true;
    key = true;
    while(waiting[i] && key)
        key = TestAndSet(lock);
    critical section
    j = (i+1) % n;
    while(j != i && !waiting[j])
         j = (j+1) % n;
    if(j == i)
         lock = false;
    else
         waiting[j] = false;
    remainder section
}