监视器和信号量之间的主要区别是什么?
Monitor 是一个旨在从多个线程访问的对象。监视器对象的成员函数或方法将强制互斥,因此在给定时间只有一个线程可能对对象执行任何操作。如果一个线程当前正在执行对象的成员函数,那么任何其他尝试调用该对象的成员函数的线程都必须等到第一个线程完成。
信号量是较低级别的对象。您可能会使用信号量来实现监视器。信号量本质上只是一个计数器。当计数器为正时,如果一个线程试图获取信号量,那么它被允许,并且计数器递减。当一个线程完成时,它会释放信号量,并增加计数器。
如果当一个线程试图获取信号量时计数器已经为零,那么它必须等到另一个线程释放信号量。如果一个线程释放信号量时多个线程正在等待,那么其中一个会得到它。释放信号量的线程不必与获取信号量的线程相同。
监视器就像公共厕所。一次只能有一个人进入。他们锁上门以防止其他人进来,做他们的事情,然后在他们离开时解锁。
信号量就像一个自行车出租点。他们有一定数量的自行车。如果您尝试租用一辆自行车并且他们有免费的,那么您可以使用它,否则您必须等待。当有人归还他们的自行车时,其他人就可以拿走它。如果你有一辆自行车,那么你可以把它交给其他人归还——自行车出租店不在乎谁归还它,只要他们把自行车拿回来。
下面的解释实际上解释了监视器的 wait() 和 signal() 与信号量的 P 和 V 有何不同。
监视器中条件变量的 wait() 和 signal() 操作类似于计数信号量的 P 和 V 操作。
等待语句可以阻塞一个进程的执行,而信号语句可以导致另一个进程被解除阻塞。但是,它们之间存在一些差异。当进程执行 P 操作时,它不一定会阻塞该进程,因为计数信号量可能大于零。相反,当等待语句被执行时,它总是阻塞进程。当任务对信号量执行 V 操作时,它要么解除阻塞等待在该信号量上的任务,要么在没有任务要解锁的情况下增加信号量计数器。另一方面,如果一个进程在没有其他进程可以解除阻塞的情况下执行信号语句,则对条件变量没有影响。信号量和监视器之间的另一个区别是,被 V 操作唤醒的用户可以立即恢复执行。相反,被信号操作唤醒的用户只有在监视器解锁时才会重新启动。此外,监视器解决方案比带有信号量的解决方案更结构化,因为数据和过程被封装在单个模块中,并且互斥是由实现自动提供的。
链接:here 供进一步阅读。希望能帮助到你。
信号量允许多个线程(最多一个设定数量)访问一个共享对象。监视器允许对共享对象进行互斥访问。
java.util.ArrayList
:它是一个对象还是多个对象的容器?嗯,两者同时存在。那么信号量是否适合控制对它的访问?我会说:不。
一行回复:
监视器:一次只能控制一个线程可以在监视器中执行。 (需要获取锁才能执行单线程)
信号量:保护共享资源的锁。 (需要获取锁才能访问资源)
信号量:
使用计数器或标志来控制对并发系统中某些共享资源的访问,意味着使用信号量。
例子:
一个只允许 50 名乘客获得任何剧院/公共汽车/火车/乐趣乘车/教室的 50 个座位(共享资源)的柜台。并且仅在有人腾出座位时才允许新乘客。指示任何浴室的空闲/占用状态的二进制标志。红绿灯是标志的好例子。他们通过调节道路上车辆的通行来控制流量(共享资源)
标志只显示资源的当前状态,不显示资源上等待或运行对象的计数或任何其他信息。
监视器 :
监视器通过与对对象感兴趣的线程进行通信来同步对对象的访问,要求它们获取访问权限或等待某些条件变为真。
例子:
父亲可以充当女儿的监护人,一次只允许她和一个男人约会。一位学校老师用指挥棒让一个孩子在课堂上发言。最后一个技术问题,帐户对象上的事务(通过线程)同步以保持完整性。
当信号量用于保护关键区域时,信号量与被保护的数据之间没有直接关系。这就是信号量可能分散在代码周围的部分原因,以及为什么很容易忘记调用等待或通知的原因,在这种情况下,结果将分别是违反互斥或永久锁定资源。
相比之下,这些坏事都不会发生在显示器上。监视器直接对数据感到厌烦(它封装了数据),并且由于监视器操作是原子操作,因此不可能编写可以访问数据而不调用入口协议的代码。监控操作完成时会自动调用退出协议。
监视器有一个内置机制,用于在继续之前以条件变量的形式进行条件同步。如果条件不满足,则该过程必须等待,直到通知它条件的变化。当一个进程等待条件同步时,监视器实现会处理互斥问题,并允许另一个进程访问监视器。
取自开放大学 M362 第 3 单元“交互过程”课程材料。
信号量是一种用于在线程之间进行协调的信号机制。示例:一个线程正在从 Internet 下载文件,而另一个线程正在分析文件。这是一个经典的生产者/消费者场景。下载文件时,生产者在信号量上调用 signal()
。消费者在同一信号量上调用 wait()
以便在信号指示文件准备好之前被阻塞。如果在消费者调用等待时信号量已经发出信号,则调用不会阻塞。多个线程可以在一个信号量上等待,但每个信号只会解除对单个线程的阻塞。
计数信号量跟踪信号的数量。例如,如果生产者连续发出 3 次信号,则 wait()
可以被调用 3 次而不会阻塞。二进制信号量不算数,只有“等待”和“信号”状态。
互斥锁(互斥锁)是由单个线程拥有的锁。只有获得锁的线程才能重新释放它。其他试图获取锁的线程将被阻塞,直到当前所有者线程释放它。互斥锁本身并不锁定任何东西——它实际上只是一个标志。但是代码可以检查互斥锁的所有权,以确保一次只有一个线程可以访问某个对象或资源。
monitor 是一种更高级别的构造,它使用底层互斥锁来确保对某些对象的线程安全访问。不幸的是,根据上下文、平台和上下文,“监视器”这个词有几种不同的含义,但在 Java 中,监视器是一个与对象隐式关联的互斥锁,可以使用 {1 } 关键字。 synchronized
关键字可应用于类、方法或块,并确保一次只有一个线程可以执行代码。