信号量与监视器 - 有啥区别?
Posted
技术标签:
【中文标题】信号量与监视器 - 有啥区别?【英文标题】:Semaphore vs. Monitors - what's the difference?信号量与监视器 - 有什么区别? 【发布时间】:2011-11-12 06:02:33 【问题描述】:监视器和信号量之间的主要区别是什么?
【问题讨论】:
您可以将监视器视为二进制信号量。 类似:***.com/q/3547030/158779 请通过这个albahari.com/threading/part2.aspx。我读过这篇文章,我读过的关于 Threading 的最好的一篇 我不认为你是对的,马克西姆。如果我没记错的话,信号量是“低级”结构,而监视器是一个成熟的对象。我记得我们在大学的操作系统课上简要介绍了监视器,但我不记得监视器与互斥体有何不同,除了它是面向对象的。我记得有一个问题可以使用监视器来解决,但是由于 C 语言的限制,我们不能在课堂上使用同样的方法。 Semaphore 和 Monitor 是非常不同的,但在功能上是相当的,因为您可以从另一个实现一个。您可以从 here 阅读 Hoare 证明它们等价的原始论文。 【参考方案1】:Monitor 是一个旨在从多个线程访问的对象。监视器对象的成员函数或方法将强制互斥,因此在给定时间只有一个线程可能对对象执行任何操作。如果一个线程当前正在执行对象的成员函数,那么任何其他尝试调用该对象的成员函数的线程都必须等到第一个线程完成。
Semaphore 是较低级别的对象。您可能会使用信号量来实现监视器。信号量本质上只是一个计数器。当计数器为正时,如果一个线程试图获取信号量,那么它被允许,并且计数器递减。当一个线程完成后,它会释放信号量,并增加计数器。
如果当一个线程试图获取信号量时计数器已经为零,那么它必须等到另一个线程释放信号量。如果一个线程释放信号量时多个线程正在等待,那么其中一个会得到它。释放信号量的线程不必与获取信号量的线程相同。
监视器就像公共厕所。一次只能有一个人进入。他们锁上门以防止其他人进来,做他们自己的事情,然后在他们离开时解锁。
信号量就像一个自行车出租点。他们有一定数量的自行车。如果您尝试租一辆自行车,而他们有免费的,那么您可以使用它,否则您必须等待。当有人归还他们的自行车时,其他人就可以拿走它。如果你有一辆自行车,那么你可以把它交给其他人归还——自行车出租的地方并不在乎谁归还,只要他们把自行车拿回来就行了。
【讨论】:
+1 非常类似于公共浴室和自行车出租场所。我永远不会忘记两者之间的区别。 您的回答似乎与***.com/a/7336799/632951.. 相矛盾。那么谁是对的? @Pacerier:我是 :-) 唯一的矛盾是高级/低级的事情。你可以从信号量构建一个监视器,它只是不是很整洁,正是因为监视器是一个比信号量更高级别的结构。信号量只是一个等待的计数器。我建议阅读“信号量小书”greenteapress.com/semaphores @AnthonyWilliams:我可能怀疑只能从信号量构建监视器的概念。另一种方式也是可能的,因此我们不能说监视器是比信号量更高级别的实体。 是的,您可以从监视器构建信号量。您始终可以从高级对象构建低级对象。高/低级别的东西是关于能力和操作范围,而不是关于哪个可以用来构建另一个。【参考方案2】:下面的解释实际上解释了监视器的 wait() 和 signal() 与信号量的 P 和 V 有何不同。
监视器中条件变量的wait()和signal()操作类似于P和 V 操作计数 信号量。
等待语句可以阻塞一个进程的执行,而信号语句可以导致另一个进程被解除阻塞。但是,它们之间存在一些差异。当一个进程执行 P 操作时,它不一定会阻塞该进程,因为计数信号量可能大于零。相反,当等待语句被执行时,它总是阻塞进程。当任务对信号量执行 V 操作时,它要么解除阻塞等待在该信号量上的任务,要么在没有任务解锁的情况下增加信号量计数器。另一方面,如果一个进程在没有其他进程要解除阻塞的情况下执行信号语句,则对条件变量没有影响。信号量和监视器之间的另一个区别是,被 V 操作唤醒的用户可以立即恢复执行。相反,被信号操作唤醒的用户只有在监视器解锁时才会重新启动。此外,监控解决方案比信号量解决方案更结构化,因为数据和过程被封装在一个模块中,并且互斥是由实现自动提供的。
链接:here 供进一步阅读。希望对您有所帮助。
【讨论】:
【参考方案3】:信号量允许多个线程(最多一个设定数量)访问一个共享对象。监视器允许对共享对象进行互斥访问。
Monitor
Semaphore
【讨论】:
但是,Monitor 与 MutEx 有何不同?互斥锁的作用与信号量完全相同,但一次只允许一个线程访问关键区域。 是的,mnitor 和 mutex 有什么区别? 值得注意的是,信号量不控制对共享对象的访问,而是控制共享资源(将包含多个对象)。 @xbonez:如果我们看java.util.ArrayList
:它是一个对象还是多个对象的容器?嗯,两者同时存在。那么信号量是否适合控制对它的访问?我会说:不。
在接受的答案本身中提到 Monitor 正在实施互斥。请参阅“监视器对象的成员函数或方法将强制互斥,因此在给定时间只有一个线程可能对对象执行任何操作”【参考方案4】:
单行答案:
监视器: 控制一次只能在监视器中执行一个线程。 (需要获取锁才能执行单线程)
信号量:一种保护共享资源的锁。 (需要获取锁才能访问资源)
【讨论】:
【参考方案5】:信号量:
使用计数器或标志来控制对并发系统中某些共享资源的访问,意味着使用 Semaphore。
例子:
-
一个只允许 50 名乘客获得任何剧院/公共汽车/火车/乐趣乘车/教室的 50 个座位(共享资源)的柜台。并且仅在有人腾出座位时才允许新乘客。
指示任何浴室的空闲/占用状态的二进制标志。
交通信号灯就是标志的好例子。它们通过调节道路上车辆的通行来控制流量(共享资源)
标志只显示资源的当前状态,不显示资源上等待或运行对象的计数或任何其他信息。
监控:
监视器通过与对对象感兴趣的线程通信来同步对对象的访问,要求它们获取访问权限或等待某个条件变为真。
例子:
-
父亲可以充当女儿的监护人,允许她一次只与一个男人约会。
一位学校老师用指挥棒让班里只有一个孩子发言。
最后是技术问题,帐户对象上的事务(通过线程)同步以保持完整性。
【讨论】:
我认为道路十字路口的红绿灯也是一个二元标志:一条道路上或正交道路上的汽车都可以行驶(互斥)因此示例(3)与(2)相同.另外我认为这些例子是信号量的极端情况(平凡的情况),可以使用监视器来实现。 wikipedia中有比较典型的例子。【参考方案6】:当信号量用于保护关键区域时,信号量与被保护的数据之间没有直接关系。这是信号量可能分散在代码周围的部分原因,以及为什么很容易忘记调用 wait 或 notify,在在这种情况下,结果将分别是违反互斥或永久锁定资源。
相比之下,这些坏事都不会发生在显示器上。监视器直接对数据感到厌烦(它封装了数据),并且由于监视器操作是原子操作,因此不可能编写可以访问数据而不调用入口协议的代码。监控操作完成后会自动调用退出协议。
监视器具有在继续之前以条件变量的形式进行条件同步的内置机制。如果条件不满足,则进程必须等待,直到通知它条件的变化。当一个进程等待条件同步时,监视器实现会处理互斥问题,并允许另一个进程访问监视器。
取自开放大学 M362 第 3 单元“交互过程”课程材料。
【讨论】:
除了,虽然信号量在一种语言中很常见并且在教科书中作为一种具有有限原子运算符的变量出现,但信号量是监视器的特殊情况--因为它是一种具有有限原子运算符的变量,因为这就是监视器。上面关于信号量是“较低级别”的论点是似是而非的。【参考方案7】:信号量是一种用于在线程之间进行协调的信号机制。示例:一个线程正在从 Internet 下载文件,而另一个线程正在分析文件。这是一个经典的生产者/消费者场景。下载文件时,生产者在信号量上调用signal()
。消费者在同一信号量上调用wait()
,以便在信号指示文件准备好之前被阻塞。如果在消费者调用等待时信号量已经发出信号,则调用不会阻塞。多个线程可以在一个信号量上等待,但每个信号只会解除对单个线程的阻塞。
计数信号量跟踪信号的数量。例如。如果生产者连续发出 3 次信号,wait()
可以被调用 3 次而不阻塞。二进制信号量不算数,只有“等待”和“信号”状态。
mutex(互斥锁)是由单个线程拥有的锁。只有获得锁的线程才能重新释放它。其他试图获取锁的线程将被阻塞,直到当前所有者线程释放它。互斥锁本身并不锁定任何东西——它实际上只是一个标志。但是代码可以检查互斥锁的所有权,以确保一次只有一个线程可以访问某个对象或资源。
monitor 是一种更高级别的构造,它使用底层互斥锁来确保对某些对象的线程安全访问。不幸的是,根据上下文、平台和上下文,“监视器”这个词有几种不同的含义,但例如在 Java 中,监视器是一个与对象隐式关联的互斥锁,可以使用 @987654324 调用@关键字。 synchronized
关键字可以应用于类、方法或块,并确保一次只有一个线程可以执行代码。
【讨论】:
以上是关于信号量与监视器 - 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章