Operating system 为什么是信号灯?

Operating system 为什么是信号灯?,operating-system,ipc,semaphore,Operating System,Ipc,Semaphore,当一个简单变量可以实现相同的功能时,为什么要使用二进制信号量?因为变量不能跨进程工作。系统信号量会限制进程间的访问,而变量,即使是应用程序的全局变量,也不能在系统范围内执行相同的操作 此外,为什么要重新发明轮子?您必须自己用一个变量来处理所有的实现,而使用信号量,该功能已经由操作系统提供并保证工作。因为信号量不是一个简单的变量,它是一个更大的结构 具体来说,对于计数信号量(实际上,二进制信号量的计数为1),增加了阻止任何试图将信号量增加到其最大值以上的进程/线程的功能 信号量还有一个附加功能,即

当一个简单变量可以实现相同的功能时,为什么要使用二进制信号量?

因为变量不能跨进程工作。系统信号量会限制进程间的访问,而变量,即使是应用程序的全局变量,也不能在系统范围内执行相同的操作


此外,为什么要重新发明轮子?您必须自己用一个变量来处理所有的实现,而使用信号量,该功能已经由操作系统提供并保证工作。

因为信号量不是一个简单的变量,它是一个更大的结构

具体来说,对于计数信号量(实际上,二进制信号量的计数为1),增加了阻止任何试图将信号量增加到其最大值以上的进程/线程的功能

信号量还有一个附加功能,即它们的状态“原子地”改变,这意味着底层内存被逻辑包围,以确保CPU缓存等被刷新,并且当值改变时,它会为“所有人”改变。这在现代多核处理器上尤为重要


当您试图保护共享资源不被过度使用时,可以使用该信号量。二进制信号量非常适合一次只能由一个进程/线程使用的资源。

信号量原子操作对于多线程代码至关重要,否则无法确定哪个线程先使用。例如,如果您有两个线程处理电子邮件请求,您希望每个人只收到一封电子邮件;您需要确定是否已处理电子邮件请求。如果没有信号灯,会发生以下情况:

Thread A checks if email[0] has been read, it has not
Thread B checks if email[0] has been read, it has not
Thread A sends email[0] and marks it as done
Thread B sends email[0] and marks it as done
对于用户,电子邮件已发送两次,因为两个线程都认为它未被处理。现在有了一个信号灯,电子邮件会发生什么情况:

Thread A marks email[0] as in progress via a semaphore
Thread B checks email[0] and sees the semaphore is marked
Thread A sends email[0] and marks it as done then unmarks the semaphore

使用信号灯时,只有一个线程将处理电子邮件。

原因有很多。因为信号量是由操作系统提供的,所以它可以

a) 可以在多个进程之间共享

b) 用于阻止正在等待的进程,而不是繁忙地等待

c) 真的很管用。由多个线程共享的变量,或者在多个进程的共享内存空间中的变量,不会提供信号量的安全性,因为您永远不知道线程/进程何时会失去控制。当您获取二进制信号量时,您知道您是该代码部分中唯一的线程/进程,操作系统保证这一点


我建议你读一本关于这方面的书,这是一个有点愚蠢的问题:)没有冒犯

实际上,信号量不像一个单一的变量。如上所述,它有很多优点。您可以阅读Allen B.Downey的《信号灯小书》(the Little book of Semaphores,第二版),了解有关信号灯的更多详细信息。

让我们假设一种实现资源保护的简单方法可以通过使用一个变量(即布尔值)来实现。我举个例子:

while {resource_protected == TRUE}
{
// resource is protected
}
现在我们可以通过设置
resource\u protected==TRUE
来保护资源

要检查资源是否可用,我们只需使用以下内容:

if {resource_protected == FALSE}
{    // <---- rescheduling possible here!
resource_protected == TRUE; // protect resource
}
else
{
//try again later
}
如果{resource_protected==FALSE}
{    //