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


当前回答

除了互斥对象有一个所有者之外,这两个对象还可以针对不同的用途进行优化。互斥锁被设计为只保留很短的时间;违反这一点会导致糟糕的性能和不公平的调度。例如,一个正在运行的线程可能被允许获取一个互斥量,即使另一个线程已经被阻塞在这个线程上。信号量可以提供更多的公平性,或者可以使用几个条件变量强制实现公平性。

其他回答

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

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

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

互斥对象有所有权,不像信号量。尽管在互斥量范围内的任何线程都可以获得一个未锁定的互斥量,并锁定对同一关键代码段的访问,但只有锁定了互斥量的线程才应该解锁它。

在窗口,差异如下所示。 MUTEX:成功执行等待的进程必须执行一个信号,反之亦然。二进制信号量:不同的进程可以在一个信号量上执行等待或信号操作。

修改问题是-互斥量和“二进制”信号量在“Linux”中的区别是什么?

答:以下是它们的区别 i)作用域——互斥锁的作用域在创建它的进程地址空间内,用于线程同步。而信号量可以跨进程空间使用,因此它可以用于进程间同步。

ii)互斥量是轻量级的,比信号量更快。Futex甚至更快。

iii)同一线程可以成功多次获得互斥锁,条件是互斥锁释放次数相同。其他线程试图获取将阻塞。而对于信号量,如果同一个进程试图再次获取它,它会阻塞,因为它只能获得一次。

答案可能取决于目标操作系统。例如,我所熟悉的至少一个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。