mutex和semaphore有什么區別呢?
mutex是用作互斥的,而semaphore是用作同步的。
也就是說,mutex的初始化一定是為1,而semaphore可以是任意的數,
所以如果使用mutex,那第一個進入臨界區的進程一定可以執行,而其他的進程必須等待。
而semaphore則不一定,如果一開始初始化為0,則所有進程都必須等待。
同時mutex和semaphore還有一個區別是,獲得mutex的進程必須親自釋放它,而semaphore則可以一個進程獲得,另一個進程釋放。
http://www.cppblog.com/martin/archive/2009/03/18/hello.html
mutex與semaphore的區別
"互斥(mutext)和旗語(semaphore)之間有什么不同?"這樣的問題簡短而有力,但要回答卻相當困難.
即使有經驗的實時操作系統(RTOS)用戶在區別如何正確使用mutex和semaphore時也存在着困難.
但這一點很不幸而且很危險,因為無任這兩種原生RTOS中的哪一種被錯誤使用,都會導致嵌入式系統出現意想不到的錯誤,特別是這些系統為有關生命安全的產品時.
有關mutex和semaphore的荒誕說法是它們是相似的,甚至是可以互換的.
正確的事實是盡管mutex和semaphore在它們的執行上有相似之處,但是我們還是應該在使用它們時加以區別對待.
最普遍(但也是不正確)的答案是:mutex和semphore非常相似,它們只有一個區別,那就是semaphores的計數可以超過1.
差不多所有的工程師都能正確的理解:mutex是一個二進制標志,可以通過它來確保執行流在代碼關鍵區(critical section of code)互相排斥,從而對共享資源加一保護.
但當他們被要求進一步回答如何使用"計算方法semaphore"的方式時,大部分工程師的回答就如同教科書書一般的刻板---semaphore用於保護多重同類資源.
通過類比辦法,我們很容易解釋為什么"多重資源"場景是有缺陷的.如果你認為一個mutex是由操作系統擁有的關鍵值的話,我們可以很容易地將個別的mutex比喻是城市咖啡店中一間浴室的鑰匙.
如果你想使用浴室,卻找不到鑰匙,你就必須在一個隊列中等候.同樣地,mutex則協串行化多項任務,以取得全域資源的共享,並且為等待隊列中的任務分配一個靜候其循序漸進的位置.
但這種簡單的資源保護協議並不使用於兩間相同浴室的情況.如果把一個semaphore概括為一個mutex,使其能保護兩個或更多相同的資源,
那么在我們的比喻中,它就象是放着兩把相同鑰匙的藍子,你可以用任何一把打開任何一扇浴室的門.
因此,semaphore本身並不能解決多個相同資源的問題.咖啡店中的客人可能只知道有一把鑰匙,但並不知道哪間浴室可用.
如果你試圖以此方式使用semaphore,你將會發現需要更多的狀態信息---它們通常是由不同的mutex所保護的共享資源.
正確使用semaphore是為了使信號從一項任務傳至另一項任務.
mutex意味着取得與釋放,使用受保護共享資源的每一次任務都是以這樣的順序進行.
相比之下,使用semaphore的任務通常不是發送信號,就是進入等待狀態,不可能同時發生.
例如,任務1可能包含程序代碼,當按下"電源"(power)按鈕時,即可提出(如發送信號或增量)一個特別的semaphore;
任務2則依據相同的semaphore而用於喚醒顯示器. 在這種情況下,其中一項任務是信號的生產者,另一項任務是信號的消費者.
用一個例子來做總結,首先展示如何使用mutex:
/* Task 1 */
mutexWait(mutex_mens_room);
// Safely use shared resource
mutexRelease(mutex_mens_room);
/* Task 2 */
mutexWait(mutex_mens_room);
// Safely use shared resource
mutexRelease(mutex_mens_room);
相應地,你總是采用下列方法使用semaphore:
/* Task 1 - Producer */
semPost(sem_power_btn); // Send the signal
/* Task 2 - Consumer */
semPend(sem_power_btn); // Wait for signal
重要的是,semaphores可以被interrupt service routine(ISR)中斷服務程序用來向task發送信號.
發送一個semaphore是一個非阻塞的RTOS行為,並且ISR安全.
因為這種技術排除了在task級別的為了是中斷不使能而引起的錯誤的可能性,
從ISR中發出信號是一種使嵌入式軟件更加可靠的設計方式.
http://ousysrobin.blog.hexun.com/57137773_d.html
理解Semaphore和Mutex
Mutex是一把鑰匙,一個人拿了就可進入一個房間,出來的時候把鑰匙交給隊列的第一個。
一般的用法是用於串行化對critical section代碼的訪問,保證這段代碼不會被並行的運行。
Semaphore是一件可以容納N人的房間,如果人不滿就可以進去,如果人滿了,就要等待有人出來。
對於N=1的情況,稱為binary semaphore。一般的用法是,用於限制對於某一資源的同時訪問。
Binary semaphore與Mutex的差異:
在有的系統中Binary semaphore與Mutex是沒有差異的。在有的系統上,主要的差異是mutex一定要由獲得鎖的進程來釋放。
而semaphore可以由其它進程釋 放(這時的semaphore實際就是個原子的變量,大家可以加或減),因此semaphore可以用於進程間同步。
Semaphore的同步功能是所有 系統都支持的,而Mutex能否由其他進程釋放則未定,
因此建議mutex只用於保護critical section。而semaphore則用於同步或者保護某變量。
關於semaphore和mutex的區別,網上有著名的廁所理論(http://koti.mbnet.fi/niclasw/MutexSemaphore.html):
The Toilet Example (c) Copyright 2005, Niclas Winquist ;)
http://www.cnblogs.com/xiangshancuizhu/p/3305609.html
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.
mutex是廁所鑰匙,一次只能一人那着這把鑰匙去廁所。結束了,這個人把鑰匙給隊列中的下一個人。
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.
信號量是一個自由的官方廁所鑰匙,我們有四個廁所,他們的鎖和鑰匙是一樣的。
信號量開始設置為4,表示4個廁所是自由滴,如果一個人進去了,數量就-1.
如果廁所滿了,鑰匙數目就為0,信號量數目這時也是0.如果一個人離開廁所,信號量+1,隊列中的下一個人可以用啦!
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
所以,mutex就是一個binary semaphore (值就是0或者1)。但是他們的區別又在哪里呢?主要有兩個方面:
* 初始狀態不一樣:mutex的初始值是1(表示鎖available),而semaphore的初始值是0(表示unsignaled的狀態)。
隨后的操 作基本一樣。mutex_lock和sem_post都把值從0變成1,mutex_unlock和sem_wait都把值從1變成0(如果值是零就等 待)。
初始值決定了:雖然mutex_lock和sem_wait都是執行V操作,但是sem_wait將立刻將當前線程block住,直到有其他線程 post;
mutex_lock在初始狀態下是可以進入的。
* 用法不一樣(對稱 vs. 非對稱):這里說的是“用法”。Semaphore實現了signal,但是mutex也有signal
(當一個線程lock后另外一個線程 unlock,lock住的線程將收到這個signal繼續運行)。
在mutex的使用中,模型是對稱的。unlock的線程也要先lock。
而 semaphore則是非對稱的模型,對於一個semaphore,只有一方post,另外一方只wait。
就拿上面的廁所理論來說,mutex是一個鑰 匙不斷重復的使用,傳遞在各個線程之間,
而semaphore擇是一方不斷的制造鑰匙,而供另外一方使用(另外一方不用歸還)。
(A mutex is really a semaphore with value 1.) ????
http://www.freertos.org/Real-time-embedded-RTOS-mutexes.html
Mutexes are binary semaphores that include a priority inheritance mechanism.
Whereas binary semaphores are the better choice for implementing synchronisation
(between tasks or between tasks and an interrupt),
mutexes are the better choice for implementing simple mutual exclusion (hence 'MUT'ual 'EX'clusion).
When used for mutual exclusion the mutex acts like a token that is used to guard a resource.
When a task wishes to access the resource it must first obtain ('take') the token.
When it has finished with the resource it must 'give' the token back -
allowing other tasks the opportunity to access the same resource.
Mutexes use the same semaphore access API functions so also permit a block time to be specified.
The block time indicates the maximum number of 'ticks' that a task should enter the Blocked state
when attempting to 'take' a mutex if the mutex is not immediately available.
Unlike binary semaphores however - mutexes employ priority inheritance.
This means that if a high priority task blocks while attempting to obtain a mutex (token)
that is currently held by a lower priority task, then the priority of the task holding the token
is temporarily raised to that of the blocking task.
This mechanism is designed to ensure the higher priority task is kept in the blocked state
for the shortest time possible, and in so doing minimise the 'priority inversion' that has already occurred.
Priority inheritance does not cure priority inversion! It just minimises its effect in some situations.
Hard real time applications should be designed such that priority inversion does not happen in the first place.
http://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html
Binary semaphores are used for both mutual exclusion and synchronisation purposes.
Binary semaphores and mutexes are very similar but have some subtle differences:
Mutexes include a priority inheritance mechanism, binary semaphores do not.
This makes binary semaphores the better choice for implementing synchronisation
(between tasks or between tasks and an interrupt), and
mutexes the better choice for implementing simple mutual exclusion.
The description of how a mutex can be used as a mutual exclusion mechanism holds equally for binary semaphores.
This sub section will only describe using binary semaphores for synchronisation.
Semaphore API functions permit a block time to be specified.
The block time indicates the maximum number of 'ticks' that
a task should enter the Blocked state when attempting to 'take' a semaphore,
should the semaphore not be immediately available.
If more than one task blocks on the same semaphore then the task with
the highest priority will be the task that is unblocked the next time the semaphore becomes available.
Think of a binary semaphore as a queue that can only hold one item.
The queue can therefore only be empty or full (hence binary).
Tasks and interrupts using the queue don't care what the queue holds -
they only want to know if the queue is empty or full.
This mechanism can be exploited to synchronise (for example) a task with an interrupt.
Consider the case where a task is used to service a peripheral.
Polling the peripheral would be wasteful of CPU resources, and prevent other tasks from executing.
It is therefore preferable that the task spends most of its time in the Blocked state (allowing other tasks to execute)
and only execute itself when there is actually something for it to do.
This is achieved using a binary semaphore by having the task Block while attempting to 'take' the semaphore.
An interrupt routine is then written for the peripheral that just 'gives' the semaphore when the peripheral requires servicing.
The task always 'takes' the semaphore (reads from the queue to make the queue empty), but never 'gives' it.
The interrupt always 'gives' the semaphore (writes to the queue to make it full) but never takes it.
The source code provided on the xSemaphoreGiveFromISR() documentation page should make this clearer.
Task prioritisation can be used to ensure peripherals get services in a timely manner
- effectively generating a 'differed interrupt' scheme.
An alternative approach is to use a queue in place of the semaphore.
When this is done the interrupt routine can capture the data associated
with the peripheral event and send it on a queue to the task.
The task unblocks when data becomes available on the queue,
retrieves the data from the queue, then performs any data processing that is required.
This second scheme permits interrupts to remain as short as possible, with all post processing instead occurring within a task.
See the Semaphores/Mutexes section of the user documentation for a list of semaphore related API functions.
Searching the files in the FreeRTOS/Demo/Common/Minimal directory will reveal multiple examples of their usage.
Note that interrupts must NOT use API functions that do not end in "FromISR" .
Using a semaphore to synchronise a task with an interrupt.
The interrupt only ever 'gives' the semaphore,
while the task only ever 'takes' the semaphore.
http://stackoverflow.com/questions/62814/difference-between-binary-semaphore-and-mutex
Their synchronization semantics are very different:
- mutexes allow serialization of access to a given resource i.e. multiple threads wait for a lock,
one at a time and as previously said, the thread owns the lock until it is done:
only this particular thread can unlock it. - a binary semaphore is a counter with value 0 and 1: a task blocking on it until any task does a sem_post.
The semaphore advertises that a resource is available, and it provides the mechanism
to wait until it is signaled as being available.
As such one can see a mutex as a token passed from task to tasks
and a semaphore as traffic red-light (it signals someone that it can proceed).
On Windows, there are two differences between mutexes and binary semaphores:
-
A mutex can only be released by the thread which has ownership,
i.e. the thread which previously called the Wait function, (or which took ownership when creating it).
A semaphore can be released by any thread. -
A thread can call a wait function repeatedly on a mutex without blocking.
However, if you call a wait function twice on a binary semaphore
without releasing the semaphore in between, the thread will block.
In windows the difference is as below.
MUTEX: process which successfully executes wait has to execute asignal and vice versa.
BINARY SEMAPHORES: Different processes can execute wait or signal operation on a semaphore.
A Mutex controls access to a single shared resource.
It provides operations to acquire() access to that resource and release() it when done.
A Semaphore controls access to a shared pool of resources.
It provides operations to Wait() until one of the resources in the pool becomes available,
and Signal() when it is given back to the pool.
When number of resources a Semaphore protects is greater than 1, it is called a Counting Semaphore.
When it controls one resource, it is called a Boolean Semaphore.
A boolean semaphore is equivalent to a mutex.
Thus a Semaphore is a higher level abstraction than Mutex.
A Mutex can be implemented using a Semaphore but not the other way around.
http://www.geeksforgeeks.org/mutex-vs-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.
http://www.geeksforgeeks.org/mutex-vs-semaphore/
Mutex vs Semaphore
What are the differences between Mutex vs Semaphore?
When to use mutex and when to use semaphore?
Concrete understanding of Operating System concepts is required to design/develop smart applications.
Our objective is to educate the reader on these concepts and learn from other expert geeks.
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.
References:
http://www.netrino.com/node/202
http://doc.trolltech.com/4.7/qsemaphore.html
Also compare mutex/semaphores with Peterson’s algorithm and Dekker’s algorithm.
A good reference is the Art of Concurrency book. Also explore reader locks and writer locks in Qt documentation.
Exercise:
Implement a program that prints a message “An instance is running” when executed more than once in the same session.
For example, if we observe word application or Adobe reader in Windows, we can see only one instance in the task manager.
How to implement it?
Article compiled by Venki.
Please write comments if you find anything incorrect, or
you want to share more information about the topic discussed above.