Related
What is the difference between semaphores and mutex provided by pthread library ?
semaphores have a synchronized counter and mutex's are just binary (true / false).
A semaphore is often used as a definitive mechanism for answering how many elements of a resource are in use -- e.g., an object that represents n worker threads might use a semaphore to count how many worker threads are available.
Truth is you can represent a semaphore by an INT that is synchronized by a mutex.
I am going to talk about Mutex vs Binary-Semaphore. You obviously use mutex to prevent data in one thread from being accessed by another thread at the same time.
(Assume that you have just called lock() and in the process of accessing a 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.)
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 ever allow 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,
with “mutex” this can’t happen. No other thread can unlock the lock
in your thread
with “binary-semaphore” this can happen. Any other thread can unlock
the lock in your thread
So, if you are very particular about using binary-semaphore instead of mutex, then you should be very careful in “scoping” the locks and unlocks, I mean, that every control-flow that hits every lock should hit an unlock call and also there shouldn’t be any “first unlock”, rather it should be always “first lock”.
The Toilet Example
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.
"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."
(A mutex is really a semaphore with value 1.)
Semaphore:
Is the number of free identical toilet keys.
For 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.
"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)."
Source
mutex is used to avoid race condition between multiple threads.
whereas semaphore is used as synchronizing element used across multiple process.
mutex can't be replaced with binary semaphore since, one process waits for semaphore while other process releases semaphore. In case mutex both acquisition and release is handled by same.
The difference between the semaphore and mutex is the difference between mechanism and pattern. The difference is in their purpose (intent)and how they work(behavioral).
The mutex, barrier, pipeline are parallel programming patterns. Mutex is used(intended) to protect a critical section and ensure mutual exclusion. Barrier makes the agents(thread/process) keep waiting for each other.
One of the feature(behavior) of mutex pattern is that only allowed agent(s)(process or thread) can enter a critical section and only that agent(s) can voluntarily get out of that.
There are cases when mutex allows single agent at a time. There are cases where it allows multiple agents(multiple readers) and disallow some other agents(writers).
The semaphore is a mechanism that can be used(intended) to implement different patterns. It is(behavior) generally a flag(possibly protected by mutual exclusion). (One interesting fact is even mutex pattern can be used to implement semaphore).
In popular culture, semaphores are mechanisms provided by kernels, and mutexes are provided by user-space library.
Note, there are misconceptions about semaphores and mutexes. It says that semaphores are used for synchronization. And mutexes has ownership. This is due to popular OS books. But the truth is all the mutexes, semaphores and barriers are used for synchronization. The intent of mutex is not ownership but mutual exclusion. This misconception gave the rise of popular interview question asking the difference of the mutexes and binary-semaphores.
Summary,
intent
mutex, mutual exclusion
semaphore, implement parallel design patterns
behavior
mutex, only the allowed agent(s) enters critical section and only it(they) can exit
semaphore, enter if the flag says go, otherwise wait until someone changes the flag
In design perspective, mutex is more like state-pattern where the algorithm that is selected by the state can change the state. The binary-semaphore is more like strategy-pattern where the external algorithm can change the state and eventually the algorithm/strategy selected to run.
This two articles explain great details about mutex vs semaphores
Also this stack overflow answer tells the similar answer.
Semaphore is more used as flag, for which your really don't need to bring RTOS / OS. Semaphore can be accidentally or deliberately changed by other threads (say due to bad coding).
When you thread use mutex, it owns the resources. No other thread can ever access it, before resource get free.
Mutexes can be applied only to threads in a single process and do not work between processes as do semaphores.
Mutex is like sempaphore with with S=1.
You can control number of concurrent accesses with semaphore but with mutex only one process at a time can access it.
See the implemenation of these two below: (all functions are atomic)
Semaphore:
wait(S) {
while (S <= 0 )
; // busy wait
S--;
}
signal(S) {
S++;
}
Mutex:
acquire() {
while (!available)
; // busy wait
available = false;
}
release() {
available = true;
}
I m using pthread_cond_wait(&cond_t, &mutex); in my program and I m wondering why this function need as a second parameter a mutex variable.
Does the pthread_cond_wait() unlock the mutex at the beggining (beggining of the execution pthread_cond_wait()) and then locked when it finish (just before leaving pthread_cond_wait())?
There are many text on the subject of condition variables and their usage, so I'll not bore you with a ton of ugly details. The reason they exist at all is to allow you to notify change in a predicate state. The following are critical in understanding proper use of condition variables and their mutex association:
pthread_cond_wait() simultaneously unlocks the mutex and begins waiting for the condition variable to be signalled. thus you must always have ownership of the mutex before invoking it.
pthread_cond_wait() returns with the mutex locked, thus you must unlock the mutex to allow its use somewhere else when finished with it. Whether the return happened because the condition variable was signalled or not isn't relevant. You still need to check your predicate regardless to account for potential spurious wakeups.
The purpose of the mutex is not to protect the condition variable; it is to protect the predicate on which the condition variable is being used as a signaling mechanism. This is hands-down the most often misunderstood idiom of pthread condition variables and their mutexes. The condition variable doesn't need mutual exclusion protection; the predicate data does. Think of the predicate as an outside-state which is being monitored by the users of the condition-variable/mutex pair.
For example, a trivial yet obviously wrong piece of code to wait for a boolean flag fSet:
bool fSet = false;
int WaitForTrue()
{
while (!fSet)
{
sleep(n);
}
}
I should be obvious the main problem is the predicate, fSet, is not protected at all. Many things can go wrong here. Ex: From the time you evaluate the while-conditon until the time you begin waiting (or spinning, or whatever) the value may have changed. If that change notification is somehow missed, you're needlessly waiting.
We can change this a little so at least the predicate is protected somehow. Mutual exclusion in both modifying and evaluating the predicate is easily provided with (what else) a mutex.
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
bool fSet = false;
int WaitForTrue()
{
pthread_mutex_lock(&mtx);
while (!fSet)
sleep(n);
pthread_mutex_unlock(&mtx);
}
Well, that seems simple enough.. Now we never evaluate the predicate without first getting exclusive access to it (by latching the mutex). But this is still a major problem. We latched the mutex, but we never release it until our loop is finished. If everyone else plays by the rules and waits for the mutex lock before evaluation or modification of fSet, they're never be able to do so until we give up the mutex. The only "someone" that can do that in this case is us.
So what about adding still more layers to this. Will this work?
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
bool fSet = false;
int WaitForTrue()
{
pthread_mutex_lock(&mtx);
while (!fSet)
{
pthread_mutex_unlock(&mtx);
// XXXXX
sleep(n);
// YYYYY
pthread_mutex_lock(&mtx);
}
pthread_mutex_unlock(&mtx);
}
Well, yes it will "work", but still is not much better. The period between XXXXX and YYYYY we don't own the mutex (which is ok, since we're not checking or modifying fSet anyway). But anytime during that period some other thread can (a) obtain the mutex, (b) modify fSet, and (c) release the mutex, and we won't know a thing about it until we finish our sleep(), once-again obtain the mutex lock, and loop around for another check.
There has to be a better way. Somehow there should be a way that we can release the mutex and begin waiting for some sort of signal that tells us a change in the predicate may have happened. Equally important, when we receive that signal and return to our code, we should already own the lock that grants us access to check the predicate data. This is exactly what a condition-variable is designed to provide.
The Condition Variable In Action
Enter the condition-variable + mutex pair. The mutex protects access to changing or checking the predicate, while the condition variable sets up a system of monitoring a change, and more importantly, doing so atomically (as far as you're concerned, anyway) with the predicate mutual exclusion:
int WaitForPredicate()
{
// lock mutex (means:lock access to the predicate)
pthread_mutex_lock(&mtx);
// we can safely check this, since no one else should be
// changing it unless they have the mutex, which they don't
// because we just locked it.
while (!predicate)
{
// predicate not met, so begin waiting for notification
// it has been changed *and* release access to change it
// to anyone wanting to by unlatching the mutex, doing
// both (start waiting and unlatching) atomically
pthread_cond_wait(&cv,&mtx);
// upon arriving here, the above returns with the mutex
// latched (we own it). The predicate *may* be true, and
// we'll be looping around to see if it is, but we can
// safely do so because we own the mutex coming out of
// the cv-wait call.
}
// we still own the mutex here. further, we have assessed the
// predicate is true (thus how we broke the loop).
// take whatever action needed.
// You *must* release the mutex before we leave. Remember, we
// still own it even after the code above.
pthread_mutex_unlock(&mtx);
}
For some other thread to signal the loop above, there are several ways to do it, the two most popular below:
pthread_mutex_lock(&mtx);
TODO: change predicate state here as needed.
pthread_mutex_unlock(&mtx);
pthread_cond_signal(&cv);
Another way...
pthread_mutex_lock(&mtx);
TODO: change predicate state here as needed.
pthread_cond_signal(&cv);
pthread_mutex_unlock(&mtx);
Each has different intrinsic behavior and I invite you to do some homework on those differences and determine which is more appropriate for specific circumstances. The former provides better program flow at the expense of introducing potentially unwarranted wake-ups. The latter reduces those wake-ups but at the price of less context synergy. Either will work in our sample, and you can experiment with how each affects your waiting loops. Regardless, one thing paramount, and both methods fulfill this mandate:
Never change, nor check, the predicate condition unless the mutex is locked. Ever.
Simple Monitor Thread
This type of operation is common in a monitor thread that acts on a specific predicate condition, which (sans' error checking) typically looks something like this:
void* monitor_proc(void *pv)
{
// acquire mutex ownership
// (which means we own change-control to the predicate)
pthread_mutex_lock(&mtx);
// heading into monitor loop, we own the predicate mutex
while (true)
{
// safe to check; we own the mutex
while (!predicate)
pthread_cond_wait(&cv, &mtx);
// TODO: the cv has been signalled. our predicate data should include
// data to signal a break-state to exit this loop and finish the proc,
// as well as data that we may check for other processing.
}
// we still own the mutex. remember to release it on exit
pthread_mutex_unlock(&mtx);
return pv;
}
A More Complex Monitor Thread
Modifying this basic form to account for a notification system that doesn't require you to keep the mutex latched once you've picked up the notification becomes a little more involved, but not by very much. Below is a monitor proc that does not keep the mutex latched during regular processing once we've established we've been served (so to speak).
void* monitor_proc(void *pv)
{
// acquire mutex ownership
// (which means we own change-control to the predicate)
pthread_mutex_lock(&mtx);
// heading into monitor loop, we own the predicate mutex
while (true)
{
// check predicate
while (!predicate)
pthread_cond_wait(&cv, &mtx);
// some state that is part of the predicate to
// inform us we're finished
if (break-state)
break;
// TODO: perform latch-required work here.
// unlatch the mutex to do our predicate-independant work.
pthread_mutex_unlock(&mtx);
// TODO: perform no-latch-required work here.
// re-latch mutex prior to heading into wait
pthread_mutex_lock(&mtx);
}
// we still own the mutex. remember to release it on exit
pthread_mutex_unlock(&mtx);
return pv;
}
Where would someone use something like that ? Well, suppose your "predicate" is the "state" of a work queue as well as some flag to tell you to stop looping and exit. Upon receiving the notification that something is "different", you check to see if you should continue executing your loop, and deciding you should continue, pop some data off the queue. Modifying the queue requires the mutex be latched (remember, its "state" is part of our predicate). Once we have popped our data, we have it locally and can process it independent of the queue state, so we release the mutex, do our thing, then require the mutex for the next go-around. There are many ways to code the above concept, including judicious use of pthread_cond_broadcast, etc. But the basic form is hopefully understandable.
This turned out to be considerably longer than I had hoped, but this is a major hurdle for people learning pthread-programming, and I feel it is worth the extra time/effort. I hope you got something out of it.
When the first thread calls pthread_cond_wait(&cond_t, &mutex); it releases the mutex and it waits till condition cond_t is signaled as complete and mutex is available.
So when pthread_cond_signal is called in the other thread, it doesn't "wake up" the thread that waits yet. mutex must be unlocked first, only then there is a chance that first thread will get a lock, which means that "upon successful return of pthread_cond_wait mutex shall have been locked and shall be owned by the calling thread."
yes it unlocks, waits for the condition to be fulfilled and then waits till it can reaquire the passed mutex.
How can a program try to lock multiple mutexes at the same time, and know which mutex it ended up unlocking. Essentially, I am looking for is an equivalent of select() but for mutexes. Does such a thing exist? If not, are there any libraries which implement it?
I'm (almost) certain that this kind of functionality ought to be implemented with a monitor (and condition variables using signal/wait/broadcast), but I think you can solve your problem with a single additional semaphore.
Assuming all your mutex objects begin in the "locked" state, create a semaphore with initial value 0. Whenever a mutex object is unlocked, increment (V) the semaphore. Then, implement select() like this:
// grab a mutex if possilbe
Mutex select(Semaphore s, Mutex[] m) {
P(s); // wait for the semaphore
for (Mutex toTry : m) {
boolean result = try_unlock(m);
if (result) return m;
}
}
Essentially, the semaphore keeps track of the number of available locks, so whenever P(s) stops blocking, there must be at least one available mutex (assuming you correctly increment the semaphore when a mutex becomes available!)
I haven't attempted to prove this code correct nor have I tested it... but I don't see any reason why it shouldn't work.
Once again, you likely want to use a monitor!
I am implementing a condition variable's wait operation. I have a struct for my condition variable. So far, my struct has a monitor, a queue, and a spinlock. But I am not sure if a condition variable should have a queue by itself. My notify looks like this:
void uthread_cv_notify (uthread_cv_t* cv) {
uthread_t* waiter_thread;
spinlock_lock(&cv->spinlock);
waiter_thread = dequeue (&cv->waiter_queue);
if(waiter_thread)
{
uthread_monitor_exit(cv->mon);
uthread_stop(TS_BLOCKED);
uthread_monitor_enter(cv->mon);
spinlock_unlock(&cv->spinlock);
}
}
But I wonder if in a notify function or a wait function I should just enqueue and dequeue in the monitor's waiting queue?
Thanks
The signal operation (that you're calling notify) should not require that the monitor be entered. This is inefficient.
It seems like you're trying to implement some clumsy old fashioned condition/monitor system in which the caller of "notify" must be inside the monitor, and it is guaranteed that if a thread is waiting, that thread gets the monitor before the "notify" caller returns to the monitor. (And that waiting thread does not have to have a loop re-testing the condition, either.)
That may be how C. A. R. Hoare initially described monitors and conditions, but the formalism is impractical/inefficient on modern multiprocessor systems, and also on threading implementations which do not have the luxury of being extremely tightly integrated with the low level scheduler (to be able to precisely control which thread gets to run when, so there are no races about who acquires a mutex first: for instance, to be able to transfer a thread from one wait queue to another, etc.)
Note how you're extending the critical section of the monitor over the spinlock_lock operation and over the dequeue operation. Neither of these belong under the monitor. The spinlock is independent, and the queue is guarded by the spinlock, not by the monitor. The monitor should protect the shared variables of the user code only (the special atomic property of of the wait operation).
So why do you need an extra queue? You are already storing all the threads that need to be notified.
Also, you probably want to do something like this:
void uthread_cv_notify (uthread_cv_t* cv) {
uthread_t* waiter_thread;
spinlock_lock(&cv->spinlock);
waiter_thread = dequeue (&cv->waiter_queue);
if(waiter_thread)
{
uthread_monitor_exit(cv->mon);
uthread_stop(TS_BLOCKED);
uthread_monitor_enter(cv->mon);
}
spinlock_unlock(&cv->spinlock);
}
This will ensure that the spin lock is always released.
What is the difference between semaphores and mutex provided by pthread library ?
semaphores have a synchronized counter and mutex's are just binary (true / false).
A semaphore is often used as a definitive mechanism for answering how many elements of a resource are in use -- e.g., an object that represents n worker threads might use a semaphore to count how many worker threads are available.
Truth is you can represent a semaphore by an INT that is synchronized by a mutex.
I am going to talk about Mutex vs Binary-Semaphore. You obviously use mutex to prevent data in one thread from being accessed by another thread at the same time.
(Assume that you have just called lock() and in the process of accessing a 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.)
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 ever allow 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,
with “mutex” this can’t happen. No other thread can unlock the lock
in your thread
with “binary-semaphore” this can happen. Any other thread can unlock
the lock in your thread
So, if you are very particular about using binary-semaphore instead of mutex, then you should be very careful in “scoping” the locks and unlocks, I mean, that every control-flow that hits every lock should hit an unlock call and also there shouldn’t be any “first unlock”, rather it should be always “first lock”.
The Toilet Example
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.
"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."
(A mutex is really a semaphore with value 1.)
Semaphore:
Is the number of free identical toilet keys.
For 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.
"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)."
Source
mutex is used to avoid race condition between multiple threads.
whereas semaphore is used as synchronizing element used across multiple process.
mutex can't be replaced with binary semaphore since, one process waits for semaphore while other process releases semaphore. In case mutex both acquisition and release is handled by same.
The difference between the semaphore and mutex is the difference between mechanism and pattern. The difference is in their purpose (intent)and how they work(behavioral).
The mutex, barrier, pipeline are parallel programming patterns. Mutex is used(intended) to protect a critical section and ensure mutual exclusion. Barrier makes the agents(thread/process) keep waiting for each other.
One of the feature(behavior) of mutex pattern is that only allowed agent(s)(process or thread) can enter a critical section and only that agent(s) can voluntarily get out of that.
There are cases when mutex allows single agent at a time. There are cases where it allows multiple agents(multiple readers) and disallow some other agents(writers).
The semaphore is a mechanism that can be used(intended) to implement different patterns. It is(behavior) generally a flag(possibly protected by mutual exclusion). (One interesting fact is even mutex pattern can be used to implement semaphore).
In popular culture, semaphores are mechanisms provided by kernels, and mutexes are provided by user-space library.
Note, there are misconceptions about semaphores and mutexes. It says that semaphores are used for synchronization. And mutexes has ownership. This is due to popular OS books. But the truth is all the mutexes, semaphores and barriers are used for synchronization. The intent of mutex is not ownership but mutual exclusion. This misconception gave the rise of popular interview question asking the difference of the mutexes and binary-semaphores.
Summary,
intent
mutex, mutual exclusion
semaphore, implement parallel design patterns
behavior
mutex, only the allowed agent(s) enters critical section and only it(they) can exit
semaphore, enter if the flag says go, otherwise wait until someone changes the flag
In design perspective, mutex is more like state-pattern where the algorithm that is selected by the state can change the state. The binary-semaphore is more like strategy-pattern where the external algorithm can change the state and eventually the algorithm/strategy selected to run.
This two articles explain great details about mutex vs semaphores
Also this stack overflow answer tells the similar answer.
Semaphore is more used as flag, for which your really don't need to bring RTOS / OS. Semaphore can be accidentally or deliberately changed by other threads (say due to bad coding).
When you thread use mutex, it owns the resources. No other thread can ever access it, before resource get free.
Mutexes can be applied only to threads in a single process and do not work between processes as do semaphores.
Mutex is like sempaphore with with S=1.
You can control number of concurrent accesses with semaphore but with mutex only one process at a time can access it.
See the implemenation of these two below: (all functions are atomic)
Semaphore:
wait(S) {
while (S <= 0 )
; // busy wait
S--;
}
signal(S) {
S++;
}
Mutex:
acquire() {
while (!available)
; // busy wait
available = false;
}
release() {
available = true;
}