二进制信号量和互斥量之间的区别
二进制信号量和互斥量之间是否有任何区别,或者它们基本相同?
解决方案
回答
互斥锁只能由已获取互斥锁的线程释放,而我们可以从任何其他线程(或者进程)发出信号通知信号,因此信号通知信号更适用于生产者-消费者这样的同步问题。
在Windows上,二进制信号量比互斥体更像事件对象。
回答
答案可能取决于目标操作系统。例如,至少一个我熟悉的RTOS实现将允许对单个OS互斥锁进行多个顺序的"获取"操作,只要它们都来自同一线程上下文中即可。在允许另一个线程获取互斥体之前,必须用相等数量的puts替换多个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。
回答
它们不是同一件事。它们用于不同目的!
虽然两种类型的信号量都具有完整/空状态并使用相同的API,但它们的用法却大不相同。
互斥信号灯
互斥信号量用于保护共享资源(数据结构,文件等)。
Mutex信号量由执行它的任务"拥有"。如果任务B尝试给任务A当前持有的互斥锁赋值,则任务B的调用将返回错误并失败。
互斥对象始终使用以下顺序:
- SemTake - Critical Section - SemGive
这是一个简单的示例:
Thread A Thread B Take Mutex access data ... Take Mutex <== Will block ... Give Mutex access data <== Unblocks ... Give Mutex
二进制信号量
二进制信号量解决了一个完全不同的问题:
- 等待任务B等待某事发生(例如,传感器跳闸)。
- 传感器跳闸并运行中断服务程序。它需要通知行程任务。
- 任务B应该运行,并为传感器跳闸采取适当的措施。然后回到等待状态。
Task A Task B ... Take BinSemaphore <== wait for something Do Something Noteworthy Give BinSemaphore do something <== unblocks
请注意,对于二进制信号量,B可以接收信号量,而A可以给出信号量。
同样,二进制信号量不能保护资源免受访问。发出信号量和接收信号量的行为从根本上是分离的。
对于相同的二进制信号量来说,给予和接受相同的任务通常没有多大意义。
回答
它们的同步语义非常不同:
- 互斥锁允许序列化对给定资源的访问,即多个线程一次等待一个锁,并且如前所述,该线程拥有该锁直到完成:只有这个特定的线程才能解锁它。
- 二进制信号量是一个值为0和1的计数器,一个任务在其上阻塞,直到任何任务执行sem_post。信号量通告资源可用,并且它提供了一种机制,等待信号通知它可用为止。
因此,可以将互斥锁看作是从一个任务传递到另一个任务的令牌,而将信号量看作是流量红灯(表示有人可以继续进行操作)。
回答
在Windows上,互斥量和二进制信号量之间有两个区别:
- 互斥锁只能由拥有所有权的线程(即先前称为Wait函数(或者在创建它时获得所有权)的线程)释放。信号量可以由任何线程释放。
- 线程可以在互斥对象上反复调用wait函数而不会阻塞。但是,如果我们在二进制信号量上调用了两次等待函数而又没有释放它们之间的信号量,则线程将阻塞。
回答
Mutex可以阻止关键区域,但是Semaphore可以实现计数。
回答
从理论上讲,它们在语义上没有什么不同。我们可以使用信号量来实现互斥锁,反之亦然(请参见此处的示例)。实际上,实现方式有所不同,它们提供的服务略有不同。
实际的区别(就围绕它们的系统服务而言)是,互斥锁的实现旨在成为一种更轻量级的同步机制。在甲骨文中,互斥锁称为闩锁,而信号量称为等待。
在最低级别上,他们使用某种原子测试和设置机制。这将读取内存位置的当前值,计算某种条件的值,并在一条不能中断的指令中写出该位置的值。这意味着我们可以获取一个互斥锁并进行测试,以查看是否有人在我们之前拥有它。
典型的互斥锁实现有一个进程或者线程执行测试设置指令并评估是否有其他任何东西设置了互斥锁。这里的关键点是,与调度程序之间没有交互,因此我们不知道(也不在乎)谁设置了锁定。然后,我们或者放弃时间片,然后在重新计划任务时重试时间片,或者执行自旋锁。自旋锁是一种类似以下的算法:
Count down from 5000: i. Execute the test-and-set instruction ii. If the mutex is clear, we have acquired it in the previous instruction so we can exit the loop iii. When we get to zero, give up our time slice.
当我们执行完受保护的代码(称为关键部分)后,我们只需将互斥锁值设置为零或者任何意味着"清除"的值即可。如果有多个任务试图获取互斥锁,则在释放互斥锁后碰巧计划的下一个任务将可以访问该资源。通常,我们将使用互斥锁来控制同步资源,其中仅在非常短的时间内才需要独占访问,通常情况下是对共享数据结构进行更新。
信号量是一个同步的数据结构(通常使用互斥锁),它具有一个计数,并且某些系统调用包装程序与调度程序进行交互的深度比互斥锁库要深一些。信号量会增加和减少,并用于阻止任务,直到准备好其他东西为止。有关此示例,请参阅生产者/消费者问题。信号量被初始化为某个值二进制信号量只是信号量被初始化为1的一种特殊情况。
基本的信号量算法如下所示:
(somewhere in the program startup) Initialise the semaphore to its start-up value. Acquiring a semaphore i. (synchronised) Attempt to decrement the semaphore value ii. If the value would be less than zero, put the task on the tail of the list of tasks waiting on the semaphore and give up the time slice. Posting a semaphore i. (synchronised) Increment the semaphore value ii. If the value is greater or equal to the amount requested in the post at the front of the queue, take that task off the queue and make it runnable. iii. Repeat (ii) for all tasks until the posted value is exhausted or there are no more tasks waiting.
在二进制信号量的情况下,两者之间的主要实际区别是围绕实际数据结构的系统服务的性质。
编辑:正如evan正确指出的那样,自旋锁会降低单处理器计算机的速度。我们只能在多处理器盒上使用自旋锁,因为在单处理器上,持有互斥锁的进程永远不会在其他任务运行时将其重置。自旋锁仅在多处理器体系结构上有用。
回答
厕所的例子很有趣:
Mutex: Is a key to a toilet. One person can have the key - occupy the toilet - at the time. When finished, the person gives (frees) the key to the next person in the queue. Officially: "Mutexes are typically used to serialise access to a section of re-entrant code that cannot be executed concurrently by more than one thread. A mutex object only allows one thread into a controlled section, forcing other threads which attempt to gain access to that section to wait until the first thread has exited from that section." Ref: Symbian Developer Library (A mutex is really a semaphore with value 1.) Semaphore: Is the number of free identical toilet keys. Example, say we have four toilets with identical locks and keys. The semaphore count - the count of keys - is set to 4 at beginning (all four toilets are free), then the count value is decremented as people are coming in. If all toilets are full, ie. there are no free keys left, the semaphore count is 0. Now, when eq. one person leaves the toilet, semaphore is increased to 1 (one free key), and given to the next person in the queue. Officially: "A semaphore restricts the number of simultaneous users of a shared resource up to a maximum number. Threads can request access to the resource (decrementing the semaphore), and can signal that they have finished using the resource (incrementing the semaphore)." Ref: Symbian Developer Library
回答
关于该主题的不错的文章:
- MUTEXVS。 SEMAPHORES第1部分:SEMAPHORES
- MUTEXVS。 SEMAPHORES第2部分:MUTEX
- MUTEXVS。 SEMAPHORES第3部分(最后部分):互斥问题
从第2部分开始:
The mutex is similar to the principles of the binary semaphore with one significant difference: the principle of ownership. Ownership is the simple concept that when a task locks (acquires) a mutex only it can unlock (release) it. If a task tries to unlock a mutex it hasn’t locked (thus doesn’t own) then an error condition is encountered and, most importantly, the mutex is not unlocked. If the mutual exclusion object doesn't have ownership then, irrelevant of what it is called, it is not a mutex.
回答
修改后的问题是" Linux"中的互斥锁和"二进制"信号量有什么区别?
答:以下是区别
i)范围互斥锁的范围在创建它的进程地址空间内,并用于线程同步。信号量可在整个过程空间中使用,因此可用于进程间同步。
ii)Mutex比信号量轻巧且速度更快。 Futex甚至更快。
iii)互斥量可以被同一线程多次成功获取,但前提是它必须释放相同的次数。尝试获取的其他线程将阻塞。而在信号量的情况下,如果相同的过程尝试再次获取它,则会阻塞,因为它只能被获取一次。
回答
除了互斥体具有所有者这一事实之外,还可以针对不同的用法优化这两个对象。互斥对象只能保留很短的时间。违反此规定可能会导致性能下降和调度不公。例如,即使另一个线程已被阻塞,正在运行的线程也可能被允许获取互斥量。信号量可以提供更多的公平性,或者可以使用多个条件变量来强制公平性。