二进制信号量和互斥量之间有区别吗?或者它们本质上是相同的?


当前回答

互斥锁:假设我们有临界区线程T1想要访问它,然后按照以下步骤进行。 T1:

锁 使用临界区 解锁

二进制信号量:它基于信号等待和信号工作。 等待将“s”的值减少1,通常“s”的值初始化为值“1”, 信号(s)使“s”值加1。如果“s”值为1表示没有人在使用临界区,当“s”值为0时表示临界区正在使用。 假设线程T2正在使用临界区,那么它遵循以下步骤。 T2:

Wait (s)//最初的s值是1,调用Wait后,它的值减少了1,即0 利用临界区 信号(s) //现在s值增加,变成1

Main difference between Mutex and Binary semaphore is in Mutext if thread lock the critical section then it has to unlock critical section no other thread can unlock it, but in case of Binary semaphore if one thread locks critical section using wait(s) function then value of s become "0" and no one can access it until value of "s" become 1 but suppose some other thread calls signal(s) then value of "s" become 1 and it allows other function to use critical section. hence in Binary semaphore thread doesn't have ownership.

其他回答

互斥锁只能由获得它的线程释放。 二进制信号量可以由任何线程(或进程)发出信号。

因此,信号量更适合于一些同步问题,如生产者-消费者。

在Windows上,二进制信号量更像事件对象而不是互斥对象。

答案可能取决于目标操作系统。例如,我所熟悉的至少一个RTOS实现允许对单个OS互斥量进行多个连续的“get”操作,只要它们都来自同一个线程上下文中。在允许另一个线程获得互斥量之前,多个get必须被相等数量的put替换。这与二进制信号量不同,对于二进制信号量,无论线程上下文如何,一次只允许一个get。

这种互斥锁背后的思想是,通过一次只允许一个上下文修改数据来保护对象。即使线程获得了互斥量,然后调用进一步修改对象的函数(并在自己的操作周围获得/放置保护互斥量),这些操作仍然应该是安全的,因为它们都发生在单个线程下。

{
    mutexGet();  // Other threads can no longer get the mutex.

    // Make changes to the protected object.
    // ...

    objectModify();  // Also gets/puts the mutex.  Only allowed from this thread context.

    // Make more changes to the protected object.
    // ...

    mutexPut();  // Finally allows other threads to get the mutex.
}

当然,在使用此特性时,必须确保单个线程中的所有访问都是安全的!

我不确定这种方法有多普遍,或者它是否适用于我所熟悉的系统之外。有关这种互斥锁的示例,请参阅ThreadX RTOS。

互斥锁:假设我们有临界区线程T1想要访问它,然后按照以下步骤进行。 T1:

锁 使用临界区 解锁

二进制信号量:它基于信号等待和信号工作。 等待将“s”的值减少1,通常“s”的值初始化为值“1”, 信号(s)使“s”值加1。如果“s”值为1表示没有人在使用临界区,当“s”值为0时表示临界区正在使用。 假设线程T2正在使用临界区,那么它遵循以下步骤。 T2:

Wait (s)//最初的s值是1,调用Wait后,它的值减少了1,即0 利用临界区 信号(s) //现在s值增加,变成1

Main difference between Mutex and Binary semaphore is in Mutext if thread lock the critical section then it has to unlock critical section no other thread can unlock it, but in case of Binary semaphore if one thread locks critical section using wait(s) function then value of s become "0" and no one can access it until value of "s" become 1 but suppose some other thread calls signal(s) then value of "s" become 1 and it allows other function to use critical section. hence in Binary semaphore thread doesn't have ownership.

互斥锁

Until recently, the only sleeping lock in the kernel was the semaphore. Most users of semaphores instantiated a semaphore with a count of one and treated them as a mutual exclusion lock—a sleeping version of the spin-lock. Unfortunately, semaphores are rather generic and do not impose any usage constraints. This makes them useful for managing exclusive access in obscure situations, such as complicated dances between the kernel and userspace. But it also means that simpler locking is harder to do, and the lack of enforced rules makes any sort of automated debugging or constraint enforcement impossible. Seeking a simpler sleeping lock, the kernel developers introduced the mutex.Yes, as you are now accustomed to, that is a confusing name. Let’s clarify.The term “mutex” is a generic name to refer to any sleeping lock that enforces mutual exclusion, such as a semaphore with a usage count of one. In recent Linux kernels, the proper noun “mutex” is now also a specific type of sleeping lock that implements mutual exclusion.That is, a mutex is a mutex.

互斥锁的简单性和效率来自于它在信号量要求之外强加给用户的附加约束。信号量是按照Dijkstra的原始设计来实现最基本的行为,而互斥锁则不同,它的用例更严格、更窄: n一次只能有一个任务持有互斥锁。也就是说,互斥锁的使用计数总是1。

Whoever locked a mutex must unlock it. That is, you cannot lock a mutex in one context and then unlock it in another. This means that the mutex isn’t suitable for more complicated synchronizations between kernel and user-space. Most use cases, however, cleanly lock and unlock from the same context. Recursive locks and unlocks are not allowed. That is, you cannot recursively acquire the same mutex, and you cannot unlock an unlocked mutex. A process cannot exit while holding a mutex. A mutex cannot be acquired by an interrupt handler or bottom half, even with mutex_trylock(). A mutex can be managed only via the official API: It must be initialized via the methods described in this section and cannot be copied, hand initialized, or reinitialized.

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

二进制信号量和互斥量的区别: 所有权: 信号量甚至可以从非当前所有者发出信号(发布)。这意味着您可以简单地从任何其他线程发布,尽管您不是所有者。

信号量是进程中的公共属性,它可以简单地由非所有者线程发布。 请用粗体字标出这个区别,这意味着很多。