Mutex vs Semaphore
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
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).”
Difference Between Semaphores and Mutex
After reading though the material above, some pretty clear distinctions should have emerged. However, I’d like to reiterate those differences again here, along with some other noticeable differences between semaphore and Mutex.
- A semaphore can be a Mutex but a Mutex can never be semaphore. This simply means that a binary semaphore can be used as Mutex, but a Mutex can never exhibit the functionality of semaphore.
- Both semaphores and Mutex (at least the on latest kernel) are non-recursive in nature.
- No one owns semaphores, whereas Mutex are owned and the owner is held responsible for them. This is an important distinction from a debugging perspective.
- In case the of Mutex, the thread that owns the Mutex is responsible for freeing it. However, in the case of semaphores, this condition is not required. Any other thread can signal to free the semaphore by using the
sem_post()
function.
- A Mutex, by definition, is used to serialize access to a section of re-entrant code that cannot be executed concurrently by more than one thread. A semaphore, by definition, restricts the number of simultaneous users of a shared resource up to a maximum number
- Another difference that would matter to developers is that semaphores are system-wide and remain in the form of files on the filesystem, unless otherwise cleaned up. Mutex are process-wide and get cleaned up automatically when a process exits.
- The nature of semaphores makes it possible to use them in synchronizing related and unrelated process, as well as between threads. Mutex can be used only in synchronizing between threads and at most between related processes (the pthread implementation of the latest kernel comes with a feature that allows Mutex to be used between related process).
- According to the kernel documentation, Mutex are lighter when compared to semaphores. What this means is that a program with semaphore usage has a higher memory footprint when compared to a program having Mutex.
- From a usage perspective, Mutex has simpler semantics when compared to semaphores.
- A Mutex allows serial access to a resource, whereas semaphores, in addition to allowing serial access, could also be used to access resources in parallel. For example, consider resource R being accessed by n number of users. When using a Mutex, we would need a Mutex “m” to lock and unlock the resource, thus allowing only one user at a time to use the resource R. In contrast, semaphores can allow n number of users to synchronously access the resource R.
- The advantage of semaphores over other synchronization mechanisms is that they can be used to synchronize two related or unrelated processes trying to access the same resource.
As per operating system terminology, the mutex and semaphore are kernel resources that provide synchronization services (also called as synchronization primitives). Why do we need such synchronization primitives? Won’t be only one sufficient? To answer these questions, we need to understand few keywords. Please read the posts on atomicity and critical section. We will illustrate with examples to understand these concepts well, rather than following usual OS textual description.
The producer-consumer problem:
Note that the content is generalized explanation. Practical details will vary from implementation.
Consider the standard producer-consumer problem. Assume, we have a buffer of 4096 byte length. A producer thread will collect the data and writes it to the buffer. A consumer thread will process the collected data from the buffer. Objective is, both the threads should not run at the same time.
Using Mutex:
A mutex provides mutual exclusion, either producer or consumer can have the key (mutex) and proceed with their work. As long as the buffer is filled by producer, the consumer needs to wait, and vice versa.
At any point of time, only one thread can work with the entire buffer. The concept can be generalized using semaphore.
Using Semaphore:
A semaphore is a generalized mutex. In lieu of single buffer, we can split the 4 KB buffer into four 1 KB buffers (identical resources). A semaphore can be associated with these four buffers. The consumer and producer can work on different buffers at the same time.
Misconception:
There is an ambiguity between binary semaphore and mutex. We might have come across that a mutex is binary semaphore. But they are not! The purpose of mutex and semaphore are different. May be, due to similarity in their implementation a mutex would be referred as binary semaphore.
Strictly speaking, a mutex is 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.
General Questions:
1. Can a thread acquire more than one lock (Mutex)?
Yes, it is possible that a thread will be in need of more than one resource, hence the locks. If any lock is not available the thread will wait (block) on the lock.
2. Can a mutex be locked more than once?
A mutex is a lock. Only one state (locked/unlocked) is associated with it. However, a recursive mutex can be locked more than once (POSIX complaint systems), in which a count is associated with it, yet retains only one state (locked/unlocked). The programmer must unlock the mutex as many number times as it was locked.
3. What will happen if a non-recursive mutex is locked more than once.
Deadlock. If a thread which had already locked a mutex, tries to lock the mutex again, it will enter into the waiting list of that mutex, which results in deadlock. It is because no other thread can unlock the mutex. An operating system implementer can exercise care in identifying the owner of mutex and return if it is already locked by same thread to prevent deadlocks.
4. Are binary semaphore and mutex same?
No. We will suggest to treat them separately, as it was explained signalling vs locking mechanisms. But a binary semaphore may experience the same critical issues (e.g. priority inversion) associated with mutex. We will cover these later article.
A programmer can prefer mutex rather than creating a semaphore with count 1.
5. What is a mutex and critical section?
Some operating systems use the same word critical section in the API. Usually a mutex is costly operation due to protection protocols associated with it. At last, the objective of mutex is atomic access. There are other ways to achieve atomic access like disabling interrupts which can be much faster but ruins responsiveness. The alternate API makes use of disabling interrupts.
6. What are events?
The semantics of mutex, semaphore, event, critical section, etc… are same. All are synchronization primitives. Based on their cost in using them they are different. We should consult the OS documentation for exact details.
7. Can we acquire mutex/semaphore in an Interrupt Service Routine?
An ISR will run asynchronously in the context of current running thread. It is not recommended to query (blocking call) the availability of synchronization primitives in an ISR. The ISR are meant be short, the call to mutex/semaphore may block the current running thread. However, an ISR can signal a semaphore or unlock a mutex.
8. What we mean by “thread blocking on mutex/semaphore” when they are not available?
Every synchronization primitive will have waiting list associated with it. When the resource is not available, the requesting thread will be moved from the running list of processor to the waiting list of the synchronization primitive. When the resource is available, the higher priority thread on the waiting list will get resource (more precisely, it depends on the scheduling policies).
9. Is it necessary that a thread must block always when resource is not available?
Not necessarily. If the design is sure ‘what has to be done when resource is not available‘, the thread can take up that work (a different code branch). To support application requirements the OS provides non-blocking API.
For example POSIX pthread_mutex_trylock() API. When the mutex is not available the function will return immediately where as the API pthread_mutex_lock() will block the thread till resource is available.
Nice articles on the topic:
From part 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.
From:
http://www.geeksforgeeks.org/mutex-vs-semaphore/
http://www.lessons99.com/mutex-vs-semaphore.html
相关推荐
`mutex`(互斥锁)和`semaphore`(信号量)都是用于实现线程同步和互斥的工具,确保同一时间只有一个线程可以访问特定的共享资源。本文将深入探讨这两种机制及其在实际编程中的应用。 一、互斥锁(Mutex) 互斥锁是...
Mutex适合控制对单个资源的互斥访问,而Semaphore可以控制对多个资源的并发访问。 8. **多线程编程的挑战** 虽然Mutex提供了线程同步,但多线程编程仍然面临诸多挑战,如死锁、活锁、饥饿等问题。理解这些概念以及...
在 Linux 下,我们可以使用 pthread_mutex_t 和 pthread_cond_t 来实现 Semaphore。pthread_mutex_t 用于创建一个互斥锁,pthread_cond_t 用于创建一个条件变量。这些变量可以用来控制多个线程的访问顺序。 Linux ...
Mutex和AutoResetEvent只是C#中众多同步原语的一部分,还包括Semaphore、Monitor、SemaphoreSlim等。理解并熟练使用这些工具,可以帮助开发者避免数据竞争,提高程序的并发性能,以及实现更复杂的线程交互逻辑。在...
在Windows环境下,我们可以使用Win32 API中的Mutex和Semaphore;而在Linux环境下,我们将依赖Pthreads库中的相应功能。 1. Mutex(互斥锁):Mutex是保证同一时间只有一个线程访问共享资源的工具。在生产者消费者...
在标题"CAS.tar.gz CAS Mutex multithread semphore"中,我们可以看出这是关于多线程环境下使用CAS(Compare and Swap)实现互斥锁(Mutex)和信号量(Semaphore)的一个资源包。这通常涉及到并发控制、线程安全和...
等待句柄是Windows操作系统级别的同步机制,如Mutex、Semaphore和Event。Mutex类提供了互斥访问,类似于lock,但可以跨越进程边界。Mutex允许多个线程等待,但在任何时候只有一个线程可以拥有它。Semaphore类则允许...
### 利用Semaphore实现SHM进程通信:深入解析与实践 #### 进程通信概述 在多进程系统中,进程间通信(IPC)是确保不同进程之间能够共享数据和协调运行的关键技术。根据《利用semaphore实现shm进程通信》一文,主要...
Lock(如NSLock、pthread_mutex等)在进入临界区时会锁定资源,其他线程无法获取;而Semaphore则允许一定数量的线程同时进入,超过限制的线程会被阻塞。在某些场景下,Semaphore可能会比Lock有更好的性能,因为它...
为跨平台(win32/linux)编程而设计的一套系统API,封装了thread,socket, mutex, semaphore, sharedmemory, int type等接口和类型。开发者使用这套接口来开发C程序时,可以做到在不同的平台上只需要一套代码,可以无视...
`pthread.h`中的关键函数包括`pthread_create()`用于创建新线程,`pthread_join()`等待线程结束,以及`pthread_mutex_t`等同步原语,用于线程间的通信和互斥访问资源。 2. **sched.h**: 此头文件提供了调度相关的...
本文将详细讨论如何在Windows环境下,利用Mutex和Semaphore这两个系统内核对象来实现读写锁。 Mutex(互斥量)是用于确保同一时间只有一个线程可以访问特定资源的同步工具。Semaphore(信号量)则可以控制同时访问...
Channel、Mutex和Semaphore通信和同步原语; coroutineScope、supervisorScope、withContext和withTimeout作用域构建器; 适用于 Android 和 UI 应用程序的MainScope() ; SupervisorJob()和...
- **互斥信号量(Mutex Semaphore)**:用于保护临界区,只允许一个进程访问,其值通常为1(二进制信号量)。 - **计数信号量(Counting Semaphore)**:允许多个进程同时访问,其值可以大于1,表示可使用的资源数量...
Delphi 多线程之 Semaphore ...此外,Semaphore 也可以与其他同步方法结合使用,例如 CriticalSection 和 Mutex,以实现更加复杂的多线程同步。 Semaphore 是一种高效的多线程同步方法,广泛应用于多种多线程场景中。
4. 同步机制:使用mutex和semaphore来实现生产者线程和消费者线程之间的同步。 在main函数中,我们首先获取命令行参数,包括生产者线程数、消费者线程数和休眠时间。然后,我们初始化缓冲区和同步机制,并创建生产...
本篇文章将深入探讨WinSocket中的四种同步方法:Event(事件)、Mutex、Semaphore和CriticalSection,并结合实际应用场景,解释它们各自的特点和使用场景。 首先,Event(事件)是Windows API提供的一种线程间通信...
要进行互斥控制,则必须用到Event、Mutex、CrititicalSection、Semaphore等互斥控制量。这个例子可以使用 Event、Mutex、CrititicalSection,你可以根据提示修改代码使用其中的一种互斥量进行测试。 我所写的例子...
Implement semaphore with mutex and conditional variable. Reason being, POSIX semaphore on Android are not used or well tested.
`WaitHandle`类是所有同步基元(如Mutex、Semaphore、EventWaitHandle)的基类,这些基元都提供了控制线程执行的能力。下面我们将深入探讨`WaitHandle`的核心概念和使用方法。 1. **线程同步**:线程同步是多线程...