二进制信号量和互斥量之间有区别吗?或者它们本质上是相同的?
当前回答
You obviously use mutex to lock a data in one thread getting accessed by another thread at the same time. Assume that you have just called lock() and in the process of accessing data. This means that you don’t expect any other thread (or another instance of the same thread-code) to access the same data locked by the same mutex. That is, if it is the same thread-code getting executed on a different thread instance, hits the lock, then the lock() should block the control flow there. This applies to a thread that uses a different thread-code, which is also accessing the same data and which is also locked by the same mutex. In this case, you are still in the process of accessing the data and you may take, say, another 15 secs to reach the mutex unlock (so that the other thread that is getting blocked in mutex lock would unblock and would allow the control to access the data). Do you at any cost allow yet another thread to just unlock the same mutex, and in turn, allow the thread that is already waiting (blocking) in the mutex lock to unblock and access the data? Hope you got what I am saying here? As per, agreed upon universal definition!,
使用“互斥”就不会发生这种情况。没有其他线程可以解锁锁 在你的帖子里 使用“二进制信号量”可以实现这种情况。任何其他线程都可以解锁 线程中的锁
因此,如果您非常注重使用二进制信号量而不是互斥量,那么在锁定和解锁的“作用域”时应该非常小心。我的意思是,每个触及每个锁的控制流都应该触及一个解锁调用,也不应该有任何“第一次解锁”,而应该总是“第一次锁定”。
其他回答
在理论层面上,它们在语义上并无不同。您可以使用信号量实现互斥量,反之亦然(参见这里的示例)。在实践中,实现是不同的,它们提供的服务也略有不同。
实际的区别(就围绕它们的系统服务而言)在于互斥锁的实现旨在成为一种更轻量级的同步机制。在oracle语言中,互斥锁被称为锁存器,而信号量被称为等待。
在最低级别,他们使用某种原子测试和设置机制。它读取内存位置的当前值,计算某种条件,并在一条不能中断的指令中写入该位置的值。这意味着您可以获得一个互斥锁,并测试是否有人在您之前拥有它。
典型的互斥量实现有一个进程或线程执行test-and-set指令,并评估是否有其他东西设置了互斥量。这里的关键点是与调度程序没有交互,因此我们不知道(也不关心)谁设置了锁。然后,我们要么放弃我们的时间片,并在任务重新调度时再次尝试它,要么执行自旋锁。自旋锁是这样一种算法:
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.
当我们完成执行受保护的代码(称为临界区)时,我们只需将互斥量的值设置为零或其他表示“清除”的值。如果有多个任务试图获取互斥量,那么下一个计划在互斥量释放后的任务将获得对资源的访问权。通常情况下,您可以使用互斥来控制同步资源,在这种资源中,只需要在很短的时间内对其进行独占访问,通常是对共享数据结构进行更新。
A semaphore is a synchronised data structure (typically using a mutex) that has a count and some system call wrappers that interact with the scheduler in a bit more depth than the mutex libraries would. Semaphores are incremented and decremented and used to block tasks until something else is ready. See Producer/Consumer Problem for a simple example of this. Semaphores are initialised to some value - a binary semaphore is just a special case where the semaphore is initialised to 1. Posting to a semaphore has the effect of waking up a waiting process.
一个基本的信号量算法如下所示:
(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正确地指出的那样,自旋锁会降低单个处理器的速度。你只能在多处理器上使用自旋锁,因为在单处理器上,持有互斥锁的进程永远不会在另一个任务运行时重置它。自旋锁只在多处理器架构上有用。
虽然二进制信号量可以用作互斥量,但互斥量是一个更具体的用例,因为只有锁定了互斥量的进程才应该解锁它。这种所有权限制使我们有可能对以下情况提供保护:
意外释放 递归死锁 任务死亡死锁
这些限制并不总是存在,因为它们降低了速度。在代码开发期间,您可以暂时启用这些检查。
例如,你可以在互斥锁中启用错误检查属性。错误检查互斥量返回EDEADLK,如果你试图锁定同一个互斥量两次,如果你解锁了一个不是你的互斥量,返回EPERM。
pthread_mutex_t mutex;
pthread_mutexattr_t attr;
pthread_mutexattr_init (&attr);
pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
pthread_mutex_init (&mutex, &attr);
一旦初始化,我们可以将这些检查放在我们的代码中,就像这样:
if(pthread_mutex_unlock(&mutex)==EPERM)
printf("Unlock failed:Mutex not owned by this thread\n");
互斥锁
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
互斥锁用于阻塞关键区域,而信号量用于计数。
既然上面的答案都不能消除困惑,这里有一个答案可以消除我的困惑。
Strictly speaking, a mutex is a locking mechanism used to synchronize access to a resource. Only one task (can be a thread or process based on OS abstraction) can acquire the mutex. It means there will be ownership associated with mutex, and only the owner can release the lock (mutex). Semaphore is signaling mechanism (“I am done, you can carry on” kind of signal). For example, if you are listening songs (assume it as one task) on your mobile and at the same time your friend called you, an interrupt will be triggered upon which an interrupt service routine (ISR) will signal the call processing task to wakeup.
来源:http://www.geeksforgeeks.org/mutex-vs-semaphore/
推荐文章
- 为什么Linux被称为单片内核?
- 如何检查Python的操作系统?
- 在Swift中,什么相当于Objective-C的“@synchronized”?
- 信号量和监视器——有什么不同?
- 如何使用JavaScript找到操作系统的详细信息?
- 我如何检查操作系统与预处理器指令?
- 如何在没有操作系统的情况下运行程序?
- 线程之间共享哪些资源?
- Windows、Mac OS X和Linux是用什么语言编写的?
- 什么时候应该使用自旋锁而不是互斥锁?
- context . start前台服务()没有调用service . start前台()
- 在c#中使用全局互斥锁的好模式是什么?
- 什么是信号量?
- 什么是私有字节、虚拟字节、工作集?
- 用简单的术语解释什么是文件描述符?