如何使用信号量实现互斥?

信号量是一个共享变量,用于实现系统进程之间的互斥。它主要有助于解决临界区问题,是一种实现进程同步的技术。

有两种类型的信号量,如下所示 -

  • 二进制信号量- 只能取两个值,0 或 1,这意味着一次只有一个进程可以进入临界区。信号量被初始化为 1。

  • 计数信号量- 可以取任何非负值 N,这意味着一次最多 N 个进程可以进入 CS。信号量初始化为 N。

临界区被 P 和 V 操作包围如下 -

  • P(s)

  • CS

  • V(s)

这些操作中的每一个都定义如下 -

Wait(P) − 每当一个进程进入 CS 时,它首先执行 P 操作,它减少信号量值,如果之后 s>=0 则进入 CS 否则添加到等待队列中。

P(Semaphore s)
{
   s = s - 1;
   if (s < 0) {
      block(p);
   }
}

Signal(V) − 当一个进程存在时,执行 CS 操作 V,这会增加信号量的值,表明另一个进程可以进入当前被 P 操作阻塞的 CS。

V(Semaphore s)
{
   s = s + 1;
   if (s >= 0) {
      wakeup(p);
   }
}

让我们看看如何使用锁变量来引入互斥 -

它使用与信号量类似的机制,但一次只有一个进程可以进入临界区并使用锁变量来实现同步,如下所示 -

while(lock != 0);
Lock = 1;
//临界区
Lock = 0;

它检查锁是否等于 0,然后将锁设置为 1,表示锁已被占用,然后进入 CS。如果锁不是 0,则等待它可用。当退出 CS 时,将 lock 设置回 0 表示锁定可用,另一个进程可以进入 CS。

锁和信号量的区别在于,锁可以在用户模式下实现,而信号量在内核模式下实现。此外,锁只允许一个进程进入 CS,而信号量可以允许多个进程进入 CS。总之,信号量是锁的泛化。