The context is like this:
a thread tries to lock a already locked mutex
the thread is put to sleep/blocking
after some while, the mutex is unlocked
Q1) What will happen then ?
will the thread be immediately put back to running? Or kernel will still wait the running thread consume its time slice and schedule the waiting thread normally?
Q2) What if the mutex is not unlocked forever? How does the kernel determine to keep the thread waiting?
Will the thread be immediately put back to running? Or kernel will still wait the running thread consume its time slice and schedule the waiting thread normally?
Typically the thread is now ready-to-run. On most systems, if there's an available core, it will begin running immediately. If not, then it will be considered the next time the scheduler is invoked on any core.
What if the mutex is not unlocked forever? How does the kernel determine to keep the thread waiting?
Typically, the first thing the thread does when it wakes up is try to lock the mutex. If it fails, it blocks again. Some implementations assign the mutex to a particular thread before they make it ready-to-run, in which case the thread wakes up with the mutex.
Implementations vary and may do anything that conforms to the requirements.
Related
What happens when you call pthread_cond_broadcast() and multiple threads wake up just to compete for the same mutex lock. One of the threads takes the mutex lock but what happens to the other threads? Do they go back to sleep? Or do they spin until the lock is available again?
What happens when you call pthread_cond_broadcast() and multiple
threads wake up just to compete for the same mutex lock. One of the
threads takes the mutex lock but what happens to the other threads? Do
they go back to sleep? Or do they spin until the lock is available
again?
When you call pthread_cond_broadcast(), all threads then waiting on the specified condition variable stop doing so. All such threads will have passed (a pointer to) the same mutex to pthread_cond_wait(), else the behavior is undefined. Each thread that was unblocked will (re)acquire that mutex before returning successfully from pthread_cond_wait(). That may require some or even all of them to block, just as if they were all contending for the same mutex under any other circumstances. They do not spin, and they do not require any further interaction with the CV for them to resume, but each one will hold the mutex locked when it returns from pthread_cond_wait(), just as it did when it called that function.
I am confused that what should I use either a mutex or a semaphore in my application,basically my application is a multithreaded server programmed using C and Pthreads. In my application one thread has a dependency over the other i.e one thread needs to wait until a condition is met in the other thread. Earlier I was using the While loop to check when the other thread set the condition as true,but While loop consumes CPU cycles needlessly i.e CPU consumption goes upto 100%.
Currently I started using a mutex in my application as follows:
pthread_mutex_lock(&t_data[rc].mutex);
pthread_mutex_unlock(&t_data[rc].mutex);
In one thread I lock the mutex and when the condition is met in the second thread I unlock it in the second thread( I have handled this doing indexing in a structure,in Which along which other items I have kept a mutex field, each thread is assigned an index when a new client makes a connection ).Using this everything is working fine and CPU consumption of server has came down to 2%.But I have one issue in my mind.
As the definition of mutex says that consider if 10 threads are running and they are sharing a common resource suppose some global variables,so when one thread locks a mutex then other threads cannot access the shared resource until the thread which has locked the mutex releases it.Same will be the case with my application. consider I have 10 active threads 5 threads will lock the mutex turn by turn and other 5 will release the mutex. If a thread has locked the mutex then other 4 threads need to wait until it has been released. so at some point of time a deadlock condition might occur if a thread locks a mutex and it didn't get released then all other threads will keep waiting.
please help me get out of this issue.Being Theoretical it might look awkward but it is a real case scenario.Please go through the question again before giving a downvote.
In your case consider use conditional variable. Make the 5 threads waiting on the condvar, and if the thread is done, signal the condvar if you want one other thread to continue run, or call broadcast to let all other blocking threads continue to run. Checkout these pthreads API:
pthread_cond_wait to wait on the condition
pthread_cond_signal to signal one thread of the waiters
pthread_cond_broadcast to signal all threads that are waiting
I'm trying to understand how pthread_cond_broadcast() works and whether is possible to "attach" thread to the waiting list (or queue) of event (broadcast signal) that already blocked by another thread.
Let's assume that we have two threads.
Thread #1 in a waiting loop
pthread_mutex_lock();
while(condition_is_false)
pthread_cond_wait();
pthread_mutex_unlock();
And somewhere in the middle of this process when thread #1 already blocked then another thread #2 calls the same or almost the same code in hope to be "attached" to the same condvar:
pthread_mutex_lock();
while(condition_is_false)
pthread_cond_wait(); or pthread_cond_timedwait()
pthread_mutex_unlock();
As I understand thread #2 would not get access to the code locked by mutex until it will unlocked. Am I right?
I'm trying to implement next case: There are some tasks which required a time to be done. During that time another thread(s) not allowed to duplicate the same task that already in a progress but wait until it will finished. And when task will finally finished then all threads must get the same result.
Your scenario is exactly the one for which condition variables are designed.
There is no problem for the second thread to achieve the lock on the mutex, because wait (and derivative) releases the mutex temporarily during wait and re-acquires it when coming back.
You should definitively read more in the abundant documentation about the concept of mutex and condition variables.
Does pthread_cond_wait put the calling thread to wait state to be waken up by pthread_cond_signal/pthread_cond_broadcast, so that it does not poll and churn the CPU?
Also, does sem_wait put the thread in wait state? If I understand correctly the mutex acquire/release methods make the threads poll continuously on the mutex and do not put the thread in waiting state.
Yes, pthread_cond_wait, when successful, causes the thread to wait until notified. That is the purpose of the call.
sem_wait will put the thread in the wait state if the semaphore cannot be decremented. In it's in a high state, then the call will return immediately.
In most situations, you needn't concern yourself with whether the locks are implemented via busy-waiting or scheduler yielding. Either way, you get the guaranteed behavior, and generally the library implementer will choose the most efficient method available on the platform on which you are running. In some cases (where you have more than one core and the expected wait time is small) that's busy-waiting.
Yes, the task which calls pthread_cond_wait() will be put into wait state:
pthread_cond_wait atomically releases mutex and cause the
calling thread to block on the condition variable cond
In the internal of current linux, it uses futex to do the stuffs.
sem_wait will block the task until either it becomes possible to
perform the decrement for the semaphore if the semaphore currently
has the value zero when call.
Regarding this:
How To Use Condition Variable
Say we have number of consumer threads that execute such code (copied from the referenced page):
while (TRUE) {
s = pthread_mutex_lock(&mtx);
while (avail == 0) { /* Wait for something to consume */
s = pthread_cond_wait(&cond, &mtx);
}
while (avail > 0) { /* Consume all available units */
avail--;
}
s = pthread_mutex_unlock(&mtx);
}
I assume that scenario here is: main thread calls pthread_cond_signal() to tell consumer threads to do some work.
As I understand it - subsequent threads call pthread_mutex_lock() and then pthread_cond_wait() (which atomically unlocks the mutex). By now none of the consumer threads is claiming the mutex, they all wait on pthread_cond_wait().
When the main thread calls pthread_cond_signal(), following the manpage, at least one thread is waken up. When any of them returns from pthread_cond_wait() it automatically claims the mutex.
So my question is: what happens now regarding the provided example code? Namely, what does the thread that lost the contest for the mutex do now?
(AFAICT the thread that won the mutex, should run the rest of the code and release the mutex. The one that lost should be stuck waiting on the mutex - somewhere in the 1st nested while loop - while the winner holds it and after it's been released start blocking on pthread_cond_wait() beacuse the while (avail == 0) will be satisfied by then. Am I correct?)
Note that pthread_cond_signal() is generally intended to wake up only one waiting thread (that's all that it guarantees). But it could wake more 'accidentally'. The while (avail > 0) loop performs two functions:
it allows the one thread guaranteed to be woken up to consume all queued work units
it prevents additional 'accidentally' awakened threads from assuming that there's work to be done, when there might not be since the initial thread would have handled all of them.
It also prevents a race condition where a work unit might have been placed on the queue after the while (avail > 0) has completed, but before the worker thread has waited on the condition again - but that race is also handled by the if test just before calling pthread_cond_wait().
Basically when a thread is awakened, all it knows is that there might be work units for it to consume, but there might not (another thread might have consumed them).
So the sequence of events that occurs when pthread_cond_signal() is called is:
the system will wake one or more threads waiting on the condition
all the threads that are awakened will then try to acquire the mutex - only one of them can acquire it at any particular moment, since that's the purpose of a mutex
that thread will then proceed, perform the work in the while (avail > 0) loop, then will release the mutex
at that point one of the other threads that were previously woken up will acquire the mutex and work the same loop, then release the mutex. Generally, there will be no work units available anymore (since the first thread would have consumed all of them), but if another thread had added an additional unit (or more), then this thread would handle that work
the next thread will acquire the mutex and perform that same set of logic
pthread_cond_wait() has to acquire given mutex once signaled/woken up. If another thread wins that race, the function blocks until the mutex is released. So from the application point of view it doesn't return until current thread holds the mutex. The wait is always done in a loop (while (avail == 0) { ... above) to make sure that application condition we are waiting for still holds (buffer not empty, more work available, etc.)
Hope this helps.
The thread that lost the contest wakes up once the mutex is unlocked, checks the condition again, then goes to sleep on the condition variable.
When any of them returns from pthread_cond_wait() it automatically claims the mutex.
Ah, but it doesn't. Not "automatically", that is, depending on what "automatically" means. You might be confused by the "atomic" semantics of pthread_cond_wait; but that semantics is played out on the entry side: a thread is somehow registered for waiting on the condition before giving up the mutex, so that there isn't any window during which the thread no longer has the mutex, and is not yet waiting on the variable.
Each thread which returns from pthread_cond_wait has to acquire the mutex and therefore contend for it. Those which lose the race for the mutex have to block on the mutex, similarly as if they called pthread_mutex_lock.
The way the mutex is acquired on exit from pthread_cond_wait can be modeled as a regular pthread_mutex_lock operation. Essentially, the threads have to queue up on the mutex in order to exit. Each thread which acquires the mutex then returns from the function; the others have to wait until that thread gives up the mutex before they are allowed to return.
No thread woken up by the signal gets the mutex "automatically", in the sense of somehow being transferred ownership due to special eligibility. Firstly, on a multiprocessor, a woken thread can lose the race to a thread already running on another processor which snatches the mutex, if it is available, or else queue to wait on the mutex ahead of the thread which received the signal. Secondly, the thread which calls pthread_cond_signal may itself not have given up the mutex, and may continue to hold it indefinitely, which means that all the woken threads will queue up on a mutex lock operation and none will emerge from pthread_mutex_lock until that thread gives up the mutex.
All that is "automatic" is that the pthread_cond_wait operation doesn't return until acquiring the mutex again, and so the application doesn't have to take the step to acquire the mutex.