信号量vs.监视器-有什么不同?

监控信号量之间的主要区别是什么?

135316 次浏览

信号量允许多个线程(最多设置一个数目)访问一个共享对象。监视器允许对共享对象的互斥访问。

Monitor

信号量

监控是一个设计用于从多个线程访问的对象。监视对象的成员函数或方法将强制互斥,因此在给定时间只有一个线程可以对对象执行任何操作。如果一个线程正在执行该对象的成员函数,那么任何试图调用该对象的成员函数的其他线程都必须等待,直到第一个线程完成。

信号量是一个较低级别的对象。您可以使用信号量来实现监视器。信号量本质上就是一个计数器。当计数器为正数时,如果线程试图获取信号量,则允许获取信号量,计数器则递减。当一个线程完成时,它释放信号量,并增加计数器。

如果当一个线程试图获取信号量时计数器已经为零,那么它必须等待另一个线程释放信号量。如果一个线程释放一个信号量时有多个线程在等待,那么其中一个线程会得到它。释放信号量的线程不一定是获取信号量的线程。

显示器就像一个公共厕所。每次只能有一个人进入。他们锁上门防止其他人进来,做他们的事情,然后在他们离开的时候打开门。

信号量就像一个自行车租赁场所。他们有一定数量的自行车。如果你想租一辆自行车,他们有一辆免费的,那么你可以骑,否则你必须等待。当有人归还自行车时,其他人就可以拿走它。如果你有一辆自行车,那么你可以把它交给别人归还——自行车租赁公司不在乎谁来归还,只要他们能把自行车拿回来就行。

下面的解释实际上解释了monitor的wait()和signal()与semaphore的P和V的区别。

监控中条件变量的wait ()信号()操作类似于计数信号量PV操作。

等待语句可以阻止一个进程的执行,而signal语句可以导致另一个进程被解除阻塞。然而,在它们之间有一些差异。当一个进程执行一个P操作时,它不一定会阻塞该进程,因为计数信号量可能大于零。相反,当执行wait语句时,它总是阻塞进程。当一个任务对一个信号量执行V操作时,它要么解除阻塞等待该信号量的任务,要么增加信号量计数器(如果没有需要解锁的任务)。另一方面,如果一个进程在没有其他进程需要解除阻塞的情况下执行一个信号语句,则对条件变量没有影响。信号量和监视器之间的另一个区别是,被V操作唤醒的用户可以毫无延迟地恢复执行。相反,被信号操作唤醒的用户只有在监视器被解锁时才会重新启动。此外,监控器解决方案比使用信号量的解决方案更具结构化,因为数据和过程封装在单个模块中,互斥由实现自动提供。

链接:在这里以进一步阅读。希望能有所帮助。

一句话回答:

监控:控制一次只能有一个线程在监视器中执行。(需要获取锁才能执行单线程)

信号量:保护共享资源的锁。(需要获取锁才能访问资源)

当一个信号量被用来保护一个关键区域时,信号量和被保护的数据之间没有直接的关系。这就是为什么信号量可能分散在代码中,以及为什么很容易忘记调用等待< em >通知< / em >的部分原因,在这种情况下,结果将分别违反互斥或永久锁定资源。

相比之下,这些不好的事情都可能发生在显示器上。监控器直接访问数据(它封装数据),由于监控器操作是原子动作,因此不可能编写不调用入口协议就可以访问数据的代码。退出协议在监视器操作完成时自动调用。

监控器有一个内置的机制,可以在继续之前以条件变量的形式进行条件同步。如果条件不满足,则流程必须等待,直到收到条件更改的通知。当一个进程等待条件同步时,监视器实现会处理互斥问题,并允许另一个进程访问该监视器。

选自开放大学M362第三单元“互动过程”课程材料。

信号量:

使用计数器或标志来控制并发系统中某些共享资源的访问,意味着使用信号量

例子:

  1. 一个只允许50名乘客获得任何剧院/公共汽车/火车/游乐设施/教室的50个座位(共享资源)的柜台。只有在有人空出座位的情况下,才允许新乘客进入。
  2. 一个二进制标志,指示任何浴室的空闲/占用状态。
  3. 交通灯是旗帜的一个很好的例子。他们通过调节道路上车辆的通行来控制流量(共享资源)

标志只显示资源的当前状态,没有计数或资源上正在等待或运行的对象的任何其他信息。

监控:

监控通过与对对象感兴趣的线程通信来同步对对象的访问,要求它们获得访问权或等待某些条件为真。

例子:

  1. 父亲可能会充当女儿的监工,只允许她一次和一个男人约会。
  2. 学校老师使用警棍,只允许一个孩子在课堂上发言。
  3. 最后一个技术问题是,同步Account对象上的事务(通过线程)以保持完整性。

信号量是一种用于线程间协调的信号机制。示例:一个线程正在从互联网下载文件,另一个线程正在分析文件。这是一个典型的生产者/消费者场景。当下载文件时,生产者在信号量上调用signal()。消费者在同一个信号量上调用wait(),以便阻塞直到信号指示文件准备好。如果在使用者调用等待时信号量已经发出信号,则调用不会阻塞。多个线程可以等待一个信号量,但是每个信号只会解除一个线程的阻塞。

计数信号量跟踪信号的数量。例如,如果生产者连续发出三次信号,wait()可以被调用三次而不阻塞。二进制信号量不算数,只是有“等待”;和“;signalled"州。

互斥锁(互斥锁)是由单个线程拥有的锁。只有获得锁的线程才能再次释放它。其他试图获取锁的线程将被阻塞,直到当前所有者线程释放它。互斥锁本身并不锁任何东西——它实际上只是一个标志。但是代码可以检查互斥锁的所有权,以确保一次只有一个线程可以访问某个对象或资源。

监控是一个更高级别的构造,它使用底层互斥锁来确保对某些对象的线程安全访问。不幸的是,“监控”这个词;根据上下文、平台和上下文的不同,监视器有不同的含义,但以Java为例,监视器是与对象隐式关联的互斥锁,可以用synchronized关键字调用。synchronized关键字可以应用于类、方法或块,并确保一次只有一个线程可以执行代码。