A thread T1 locks mutex M successfully and then gets preempted.
A thread T2 tries to lock mutex M but it can't yet.
The threads both have the same priority.
How do modern OS thread schedulers handle this: Is T1 immediately allowed to resume, or is there no guarantee at all?
Related
When a thread waits on a condition variable, the associated mutex is (atomically) released (unlocked). When that condition variable is signaled (by a different thread), one (for signal) or all (for broadcast) waiting thread(s) is/are awakened, automatically re-acquiring (locking) the mutex.
What will happen if one or more other threads are waiting to acquire (lock) that same mutex, but not waiting on the same condition? Are the thread(s) waiting on the condition variable guaranteed to be awakened (and thus acquire the mutex) before the mutex can be acquired (locked) by the other threads, or could the other thread(s) acquire (lock) the mutex before the thread(s) waiting on the condition variable?
[Note: the example below is simplified for clarity. Thread_B does not really start Thread_C, but Thread_C is guaranteed to not be running until after Thread_B has acquired the mutex - it does not compete with Thread_B for the mutex after Thread_A waits on the condition variable]
Thread_A:
pthread_mutex_lock(&myMutex);
while (!someState) {
pthread_cond_wait(&myCondVar,&myMutex);
}
// do something
pthread_mutex_unlock(&myMutex);
Thread_B:
pthread_mutex_lock(&myMutex);
// do other things
someState = true;
// start Thread_C here
pthread_cond_signal(&myCondVar);
pthread_mutex_unlock(&myMutex);
Thread_C:
pthread_mutex_lock(&myMutex);
// can I reach this point after Thread_B releases the mutex,
// but before Thread_A re-acquires it after being signaled?
// do things that may interfere with Thread_A...
pthread_mutex_unlock(&myMutex);
Edit: The accepted answer below was chosen because it makes clear that whether or not a reader agrees with the interpretation given, there is enough ambiguity that the only safe assumption to make is that of the respondent. Note that others well-versed in C++-standard-speak may find the text totally unambiguous... I am not in that group.
There's nothing special about acquiring a mutex when awakened from pthread_cond_[timed]wait() compared to any other thread already blocked in pthread_mutex_lock() trying to acquire the same mutex.
Per the POSIX 7 pthread_cond_signal() documentation (bolding mine):
If more than one thread is blocked on a condition variable, the scheduling policy shall determine the order in which threads are unblocked. When each thread unblocked as a result of a pthread_cond_broadcast() or pthread_cond_signal() returns from its call to pthread_cond_wait() or pthread_cond_timedwait(), the thread shall own the mutex with which it called pthread_cond_wait() or pthread_cond_timedwait(). The thread(s) that are unblocked shall contend for the mutex according to the scheduling policy (if applicable), and as if each had called pthread_mutex_lock().
Acquiring the mutex after waking up from pthread_cond_[timed]wait() is required to be exactly as if the thread had called pthread_mutex_lock().
In short, any of the threads can acquire the mutex.
Let's say I have two groups of threads. One group's function is to add an element to an array, and the other group's function is to remove an element from the array if the array contains the same element. The rule is that thread can't remove an element from the array if it's empty and it must wait. A monitor is used to solve this synchronization problem.
Consider a scenario in which all threads start at the same time, the consumer thread locks the mutex first and then it checks if the array is not empty, the condition is false, so it unlocks the mutex. Then the producer thread locks the mutex first, adds an elements and notifies all the waiting threads and unlocks the mutex. The question is, does the waiting thread gets the access to the mutex first after it was notified and the waiting thread can try to remove the element or the mutex is free again and any thread can lock it by chance again and the waiting thread is not finished after the condition fail, but let's say it's put back into the thread pool.
First, lets make some things clear (Includes an essence of cppreference's page about std::condition_variable):
Consumers
Consumers wait on std::condition_variable-s using the following steps:
Acquire a std::unique_lock<std::mutex>, on the same mutex as used to protect the shared variable
Execute wait, wait_for, or wait_until. The wait operations atomically release the mutex and suspend the execution of the thread.
When the condition variable is notified, a timeout expires, or a spurious wakeup occurs, the thread is awakened, and the mutex is atomically reacquired. The thread should then check the condition and resume waiting if the wake up was spurious.
Producers
Producers notify the same std::condition_variable-s following these steps:
Acquire a std::mutex (typically via std::lock_guard)
Perform the modification while the lock is held
Execute notify_one or notify_all on the std::condition_variable (the lock does not need to be held for notification)
Answer
does the waiting thread gets the access to the mutex first after it was notified and the waiting thread can try to remove the element
Yes, there may be multiple consumers on the same condition, and each and every one of them may consume the single object, this is why every waiting thread should protect against spurious wake-ups using an additional logical condition (See the bold text in the consumer part). The wait methods of std::condition_variable even has a specific prototype that already includes it:
template< class Predicate >
void wait( std::unique_lock<std::mutex>& lock, Predicate pred );
When the consumer wakes up, it has already acquired the lock! So, if the condition (for example !queue->empty()) is fulfilled, it can safely consume.
I was going thorugh implementation of multiple readers /writer lock mentioned here
MultiplereadersWriterLock
Here code for EnterReader is
void EnterReader(void)
{
EnterCriticalSection(&m_csWrite);
EnterCriticalSection(&m_csReaderCount);
if (++m_cReaders == 1)
ResetEvent(m_hevReadersCleared);
LeaveCriticalSection(&m_csReaderCount);
LeaveCriticalSection(&m_csWrite);
}
As per my understanding with this lock we are solving problem where we can read shared resource via multiple threads .So it means multiple threads can call EnterReader function and without blocking they can continue to read.
Example
Thread T1 calls EnterReader()
It acquires m_csWrite
It acquires m_csReaderCount
Interrupted by CPU and thread T2 starts
Thread T2 calls EnterReader()
Since m_csWrite already acquired by T1 so how thread T2 can perform read.
T2 cannot proceed further since m_csWrite is already acquired that means T2 reader thread is blocked and waiting for T1 to get finish.
I am confused how this implementation is solving problem of multiple readers accessing shared resource.
EnterReader just does a quick lock to increment the count of the readers. Notice it releases the locks before returning. When reading, m_csWrite doesn't stay locked between EnterReader and LeaveReader calls like it does between EnterWriter and LeaveWriter.
Usage example:
lock->EnterReader();
/*Do the reading*/ //No locks here. m_csReaderCount is blocking writes.
lock->LeaveReader();
I want to use pthreads and pthread_mutexes in a C++ program. I don't have any actual code yet, just a question on how mutexes work. If I have thread 1 lock a mutex, then n number of other threads attempt to lock that same mutex, what will the behavior be when thread 1 unlocks the mutex? If thread 1 acquires the lock, then thread 2 attempts to lock, then thread 3 attempts to lock, will thread 2 have priority over thread 3 when the lock is released?
Here is a more organized timeline of the locking would look:
thread 1 acquires lock
thread 2 attempts to lock
thread 3 attempts to lock
thread 4 attempts to lock
thread 1 unlocks mutex
??
in other words, I'd like the threads to execute in the order in which they attempt to acquire the lock/are created. if there is a better way to do this, I'm more than open to suggestions.
No - there will be no such guaranteed ordering. After thread 1 releases the mutex thread 3 could get or thread 2 could get it. You can't predict that.
Read this for an explanation.
I figured I'd post my solution so others could see a potential fix:
My main thread is the thread that creates worker threads by locking a creation mutex and putting each thread into a std::queue.
at the start of main, I create a manager thread and that is in an infinite while loop which checks to see if the queue is empty every cycle. when the manager thread sees the queue is nonempty
(if(! queue::empty())), it waits to acquire the lock and then creates the front thread, pops it from the queue, executes a pthread_join() on the thread and loops back around for the next thread.
I am currently trying to create a very simple thread pool using std::thread.
In order to maintain threads 'alive' after their given task is done, I associate a std::mutex with each one of them.
The principle is somewhat like this:
// Thread loop
while (1)
{
m_oMutex->lock();
m_oMutex->unlock();
m_bAvailable = false;
m_oTask();
m_bAvailable = true;
}
// ThreadPool function which gives a task to a thread
void runTask(boost::function<void ()> oTask)
{
[...]
m_oThreads[i]->setTask(oTask);
m_oMutexes[i]->unlock(); // same mutex as thread's m_oMutex
m_oMutexes[i]->lock();
}
To find the i, the ThreadPool searches for a thread object with m_bAvailable set to true. It unlocks the corresponding mutex so the thread can lock it and execute its task. The thread unlocks it immediately so the ThreadPool can lock it again so the thread is halted once its task is done.
But the question is, will locks be made in the order the threads ask them? In other words, if a thread does a lock on a mutex, then the ThreadPool unlocks it and locks it again, am I sure that the lock will be given to the thread first? If not, is there a way to ensure it?
No, you cannot guarantee that your thread loop will ever acquire the lock with your example as is. Use a conditional variable to signal to the thread loop that it should awake and take the lock. See std::condition_variable::wait(...).
condition-variable
More on this topic in general can be found here http://en.wikipedia.org/wiki/Condition_variable. If you were using the pthread library, the equivalent call would be pthread_cond_wait in your "Thread loop" and pthread_cond_signal in your runTask function.