【发布时间】:2015-03-13 19:29:48
【问题描述】:
我环顾四周,似乎无法找到问题的答案。我一直试图围绕信号量以及它们实际实现的位置。我了解信号量是一种操作系统功能,但也可以在应用程序级程序中使用。我的问题是,当操作系统(我认为)应该处理访问问题时,为什么需要在应用程序中使用信号量?
【问题讨论】:
标签: kernel system mutex semaphore
我环顾四周,似乎无法找到问题的答案。我一直试图围绕信号量以及它们实际实现的位置。我了解信号量是一种操作系统功能,但也可以在应用程序级程序中使用。我的问题是,当操作系统(我认为)应该处理访问问题时,为什么需要在应用程序中使用信号量?
【问题讨论】:
标签: kernel system mutex semaphore
信号量是一种变量或抽象数据类型,用于控制多个进程对并发系统(例如多道程序操作系统)中公共资源的访问。
将信号量视为一种有用的方式是记录特定资源的可用单位数量,以及在需要或变得空闲时安全地(即,没有race conditions)调整该记录的操作,并且,如有必要,请等到一个资源单元可用。信号量是防止竞态条件的有用工具;
【讨论】:
应用程序是一组进程,它们都执行不同的代码。
假设有 2 个进程 - A 和 B 在一个应用程序中。 A 和 B 想要以另一种方式访问特定文件 - “play.txt”。我的意思是 A 先访问,然后是 B,然后是 A,依此类推。
操作系统不知道这个执行顺序。操作系统只知道内核进程,这就是为什么它必须由用户实现。用户将在其程序中使用信号量,操作系统将读取信号量以了解有关这两个进程的所有信息。
【讨论】:
信号量是操作系统提供的一种数据类型,用于进程同步。
信号量有两个原子操作(原子意味着完全执行或根本不执行)等待和信号。在这两个操作期间不会发生上下文切换,因为它们是原子的。
程序员必须实现这些操作,以便操作系统在某些重要操作期间不会进行上下文切换。
例如阅读器作者问题。
注意:- 操作系统非常复杂,操作系统的概念是为了让我们了解操作系统的工作原理。但当前系统的工作可能与每十年计算机系统在操作系统和硬件方面的升级一样。操作系统实现了各种概念以保持其运行并提供更好的 CPU 利用率。
【讨论】:
信号量用于保护对在两个更独立运行的线程或进程之间共享的数据结构的访问。您可能会遇到信号量描述中使用的短语“临界区”;忽略它。您不用信号量保护代码,而是保护共享数据结构。
假设你有这些变量:
int savings;
int house_payment;
并且您想将一些钱从储蓄桶中转移到 house_payment 桶中。在此过程中,另一个流程需要知道您的银行余额和贷款余额。
流程 A 收到付款,从储蓄中减去价值。 然后进程 A 将该值添加到 house_payment 存储桶中。
现在假设流程 B 需要检查负载平衡和您的储蓄余额。由于流程不同步,因此流程 B 会查看流程 A 从您的储蓄中取出钱时的值,但在流程 A 可以将付款添加到您的 house_payment 之前。
就流程 B 而言,储蓄桶的钱太少,而 house_payment 桶的钱不够。您的房屋付款在运输途中丢失了。如果流程 B 再看一遍,丢失的钱神奇地出现在 house_payment 桶中。
为了防止该窗口,使用了信号量。进程 A 在转账时获取信号量,并在将钱放入 house_payment 存储桶后释放信号量。
进程 B 在访问 Savings 和 house_payment 存储桶之前获取信号量,并在完成后释放信号量。
使用信号量保护对共享数据的访问,两个进程都不会看到由于在资金传输过程中检查存储桶而导致的不一致状态。
现在,操作系统无法知道何时应用信号量防护。这是应用程序必须管理的。
【讨论】:
是的,操作系统应该处理访问问题,而信号量只是帮助它做到这一点。 试着这样理解: 有一条铁路,有 4 列火车(比如火车 A、B、C、D)等待进入铁路。现在,条件是,在给定的实例中,只有一列火车可以访问它。所以,站长所做的,就是给火车的每个司机一个灯泡。如果火车(比如火车A)的灯泡亮着,这意味着火车A有使用铁路的许可。当 A 使用道路时,火车 B、C、D 将等待(在等待队列中),并且它们的灯泡关闭。 协议是,一旦火车 A 完成使用道路,它会关闭其灯泡并且队列中的下一列火车(例如,火车 B)打开其灯泡并使用道路。这种情况一直持续到队列中的所有火车都有机会。
在这种情况下,灯泡是信号量,火车是进程/作业,铁路是关键部分(共享资源)。
【讨论】: