【问题标题】:Difference between binary semaphore and mutex二进制信号量和互斥量之间的区别
【发布时间】:2010-09-08 22:25:59
【问题描述】:

二进制信号量和互斥量之间有什么区别还是它们本质上是一样的?

【问题讨论】:

  • 它们在语义上是相同的,但在实践中你会发现奇怪的差异(尤其是在 Windows 上)。
  • @Michael Foukarakis:有什么奇怪的区别?
  • 我想奇怪不是正确的表达方式。互斥体还支持所有权,有时还支持重入。在 Windows 中就是这种情况。此外,Windows 中的信号量是在 Event 对象之上实现的,但是,我不确定这样做的实际意义。
  • @philipxy 很好地隐藏了 'rn' 代替了 'm'。
  • @Mooncrater 哇。好眼力。我预计它是由于 OCR。 (Yes, it is.)

标签: operating-system mutex semaphore binary-semaphore


【解决方案1】:

基本问题是并发性。控制流不止一种。考虑使用共享内存的两个进程。现在一次只有一个进程可以访问共享内存。如果多个进程一次访问共享内存,共享内存的内容就会被破坏。它就像一条铁轨。只有一列火车可以在上面运行,否则会发生事故。所以有一个信号机制,司机检查。如果信号是绿色的,火车可以开行,如果是红色的,则必须等待才能使用轨道。类似地,在共享内存的情况下,有一个二进制信号量。如果信号量为 1,则进程获取它(使其为 0)并继续访问它。如果信号量为 0,则进程等待。二进制信号量必须提供的功能是互斥(或简称互斥),因此只有许多并发实体(进程或线程)中的一个会相互排斥其他实体。我们有计数信号量是一个优点,它有助于同步资源的多个实例。

互斥是信号量提供的基本功能。现在在线程的上下文中,我们可能有不同的名称和语法。但是底层的概念是一样的:如何在并发编程中保持代码和数据的完整性。在我看来,所有权和相关检查等内容是实现提供的改进。

【讨论】:

    【解决方案2】:

    最佳解决方案

    唯一的区别是

    1.Mutex -> lock 和 unlock 属于锁定 mutex 的线程。

    2.Semaphore -> 没有所有权,即;如果一个线程调用 semwait(s),任何其他线程都可以调用 sempost(s) 来解除锁定。

    【讨论】:

      【解决方案3】:

      MUTEX

      直到最近,内核中唯一的休眠锁是信号量。大多数信号量用户实例化一个计数为 1 的信号量,并将它们视为互斥锁——自旋锁的休眠版本。不幸的是,信号量相当通用,并没有施加任何使用限制。这使得它们对于在不明确的情况下管理独占访问很有用,例如内核和用户空间之间的复杂舞蹈。但这也意味着更简单的锁定更难执行,并且缺乏强制规则使得任何类型的自动调试或约束强制都变得不可能。为了寻求更简单的睡眠锁,内核开发人员引入了互斥锁。是的,正如您现在所习惯的那样,这是一个令人困惑的名字。让我们澄清一下。术语“互斥锁”是一个通用名称,指的是任何强制互斥的休眠锁,例如使用计数为 1 的信号量。在最近的 Linux 内核中,专有名词“mutex”现在也是一种特定类型的实现互斥的睡眠锁。也就是说,互斥锁就是互斥锁。

      互斥体的简单性和效率来自于它对用户施加的额外约束,超出了信号量的要求。与根据 Dijkstra 的原始设计实现最基本行为的信号量不同,互斥锁具有更严格、更窄的用例: n 一次只有一个任务可以持有互斥锁。也就是说,互斥体上的使用计数始终为 1。

      1. 锁定互斥锁的人必须将其解锁。也就是说,您不能将互斥锁锁定在一个 上下文,然后在另一个中解锁它。这意味着互斥锁不适合内核和用户空间之间更复杂的同步。大多数用例, 但是,在同一上下文中干净利落地锁定和解锁。
      2. 不允许递归锁定和解锁。也就是说,您无法递归获取相同的互斥体,也无法解锁未锁定的互斥体。
      3. 进程在持有互斥锁时无法退出。
      4. 中断处理程序或下半部分无法获取互斥锁,即使使用 mutex_trylock()。
      5. 只能通过官方 API 管理互斥锁:它必须通过本节中描述的方法进行初始化,并且不能复制、手动初始化或重新初始化。

      [1] Linux 内核开发,第三版 Robert Love

      【讨论】:

        【解决方案4】:

        我认为这里的大多数答案都令人困惑,尤其是那些说互斥锁只能由持有它的进程释放但信号量可以由任何进程发出信号的人。就信号量而言,上述行有点模糊。要理解我们应该知道信号量有两种,一种称为计数信号量,另一种称为二进制信号量。计入信号量句柄访问 n 个资源,其中 n 可以在使用前定义。每个信号量都有一个计数变量,它保存正在使用的资源数量的计数,最初,它被设置为 n。每个希望使用资源的进程都会对信号量执行 wait() 操作(从而减少计数)。当进程释放资源时,它会执行 release() 操作(增加计数)。当计数变为 0 时,所有资源都在使用中。之后,进程等待直到计数大于 0。现在这里是 catch 只有持有资源的进程可以增加计数,其他进程不能增加计数只有持有资源的进程可以增加计数和进程等待信号量再次检查,当它看到可用资源时,它再次减少计数。所以就二进制信号量而言,只有持有信号量的进程才能增加计数,并且计数保持为零,直到它停止使用信号量并增加计数,其他进程才有机会访问信号量。

        二进制信号量和互斥量的主要区别在于,信号量是一种信号机制,而互斥量是一种锁定机制,但二进制信号量的功能似乎与互斥量类似,会造成混乱,但两者都是不同的概念,适用于不同的工作。

        【讨论】:

          【解决方案5】:

          你可以清楚地记住区别:

          1. 互斥锁:用于保护关键区域, 互斥锁不能跨进程使用,只能单进程使用

          2. 信号量:用于指示资源的可用性。 信号量既可以跨进程使用,也可以跨进程使用。

          【讨论】:

          【解决方案6】:

          互斥量是任何旨在解决临界区问题的算法都必须遵循的标准(共 4 个),而二进制信号量本身是一个可以取值 0 和 1 的变量。

          【讨论】:

            猜你喜欢
            • 2020-04-05
            • 2015-05-24
            • 2017-11-19
            • 2015-01-23
            • 2013-07-01
            • 1970-01-01
            • 2022-11-01
            • 2014-06-24
            • 2021-08-14
            相关资源
            最近更新 更多