Do mutex locks happen in the same order they are asked? - c++

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.

Related

Understanding condition_variable::wait for blocking a thread

While implementing a thread pool pattern in C++ based on this, I came across a few questions.
Let's assume minimal code sample:
std::mutex thread_mutex;
std::condition_variable thread_condition;
void thread_func() {
std::unique_lock<std::mutex> lock(thread_mutex);
thread_condition.wait(lock);
lock.unlock();
}
std::thread t1 = std::thread(thread_func);
Regarding cppreference.com about conditon_variable::wait(), wait() causes the current thread to block. What is locking the mutex then for when I only need one thread at all using wait() to get notified when something is to do?
unique_lock will block the thread when the mutex already has been locked by another thread. But this wouldn't be neccesary as long as wait() blocks anyway or what do I miss here?
Adding a few lines at the bottom...
std::thread t2 = std::thread(thread_func);
thread_condition.notify_all()
When unique_lock is blocking the thread, how will notify_all() reach both threads when one of them is locked by unique_lock and the other is blocked by wait()? I understand that blocking wait() will be freed by notify_all() which afterwards leads to unlocking the mutex and that this gives chance to the other thread for locking first the mutex and blocking thread by wait() afterwards. But how is this thread notified than?
Expanding this question by adding a loop in thread_func()...
std::mutex thread_mutex;
std::condition_variable thread_condition;
void thread_func() {
while(true) {
std::unique_lock<std::mutex> lock(thread_mutex);
thread_condition.wait(lock);
lock.unlock();
}
}
std::thread t1 = std::thread(thread_func);
std::thread t2 = std::thread(thread_func);
thread_condition.notify_all()
While reading documentation, I would now expect both threads running endlessly. But they do not return from wait() lock. Why do I have to use a predicate for expected behaviour like this:
bool wakeup = false;
//[...]
thread_condition.wait(lock, [] { return wakeup; });
//[...]
wakeup = !wakeup;
thread_condition.notify_all();
Thanks in advance.
This is really close to being a duplicate, but it's actually that question that answers this one; we also have an answer that more or less answers this question, but the question is distinct. I think that an independent answer is needed, even though it's little more than a (long) definition.
What is a condition variable?
The operational definition is that it's a means for a thread to block until a message arrives from another thread. A mutex alone can't possibly do this: if all other threads are busy with unrelated work, a mutex can't block a thread at all. A semaphore can block a lone thread, but it's tightly bound to the notion of a count, which isn't always appropriate to the nature of the message to receive.
This "channel" can be implemented in several ways. Very low-tech is to use a pipe, but that involves expensive system calls. Windows provides the Event object which is fundamentally a boolean on whose truth a thread may wait. (C++20 provides a similar feature with atomic_flag::wait.)
Condition variables take a different approach: their structural definition is that they are stateless, but have a special connection to a corresponding mutex type. The latter is necessitated by the former: without state, it is impossible to store a message, so arrangements must be made to prevent sending a message during some interval between a thread recognizing the need to wait (by examining some other state: perhaps that the queue from which it wants to pop is empty) and it actually being blocked. Of course, after the thread is blocked it cannot take any action to allow the message to be sent, so the condition variable must do so.
This is implemented by having the thread take a mutex before checking the condition and having wait release that mutex only after the thread can receive the message. (In some implementations, the mutex is also used to protect the workings of the condition variable, but C++ does not do so.) When the message is received, the mutex is re-acquired (which may block the thread again for a time), as is necessary to consult the external state again. wait thus acts like an everted std::unique_lock: the mutex is unlocked during wait and locked again afterwards, with possibly arbitary changes having been made by other threads in the meantime.
Answers
Given this understanding, the individual answers here are trivial:
Locking the mutex allows the waiting thread to safely decide to wait, given that there must be some other thread affecting the state in question.
If the std::unique_lock blocks, some other thread is currently updating the state, which might actually obviate the need for wait.
Any number of threads can be in wait, since each unlocks the mutex when it calls it.
Waiting on a condition variable, er, unconditionally is always wrong: the state you're after might already apply, with no further messages coming.

Use multiple std::unique_lock on mutex, all threads in FIFO to wait process?

When I have three threads or more, if mutex unlock in one thread, which one will be the next to process? They are in FIFO rule? If not FIFO, several thread wait unlock(), will have a thread never process? Do they wait in a sorted queue and what is the rule to sort them?
Sample code:
//thread No.1
func1(){
std::unique_lock<mutex> lock(_mtx);
//do something, now in here,and will leave this thread then mutex will unlock
}
//thread No.2
func2(){
std::unique_lock<mutex> lock(_mtx);
//do something
}
//thread No.3
func3(){
std::unique_lock<mutex> lock(_mtx);
//do something
}
The operating system will decide on which thread getting the mutex is the most efficient. It is your responsibility to ensure that whatever thread gets scheduled does work that you need it to do.
Generally, it's not possible for a thread to be denied the mutex for very long because eventually all the other threads will either block or exhaust their timeslices, allowing that thread to acquire the mutex. But the platform doesn't provide any particular guarantee of fairness.
You wouldn't want FIFO. That would be a complete disaster. Imagine if each thread needed to acquire the lock 100 times. Now one thread gets the lock, releases it, and then tries to get the lock against almost immediately. Do you want it to stop and switch to one of the other threads every time? Do you want 300 context switches and start/stops? You definitely don't.

Can a single thread double-lock a mutex?

If I want a thread to pause for a while, until certain conditions are met, can I double-lock the mutex?
Here's a basic example of the idea I'm working with right now:
class foo
{
public:
static std::mutex processingMutex;
void infinite_processing_loop()
{
processingMutex.lock(); // Lock the mutex, initially
while(true)
{
if ( /*ready for this thread to process data*/ )
{
// ... perform one round of data processing ...
}
else // NOT ready for this thread to process data
{
/* Pause this thread,
and wait for another thread to unlock this mutex
(when more data might be ready for processing) */
processingMutex.lock();
}
}
processingMutex.unlock(); // Will never be executed
}
};
Will the processing thread halt, when it tries to double-lock the mutex?
And can another thread unlock the same mutex, causing the halted processing thread to resume?
Or does std::mutex automatically recognize when mutex is locked twice from the same processing thread?
std::mutex will usually deadlock on second attempt to lock by the owner thread. And even if it didn't, it's considered a bug for an application to attempt with this primitive.
std::recursive_mutex will allow re-entrant locks. So if you lock twice, you need to unlock twice before the mutex is available for other threads to grab.
There's a school of thought that any design that involves recursively acquiring a mutex after it's already been locked is a design flaw. I'll try to dig up that thread and add it.

C++ Mutexes- Check if another thread is waiting

Is it possible for a thread that already has a lock on a mutex to check whether another thread is already waiting, without releasing the mutex? For example, say a thread has 3 tasks to run on a block of data, but another thread may have a short task to run on the data as well. Ideally, I'd have the first thread check whether another thread is waiting between each of the three tasks and allow the other thread to execute its task before resuming the other two tasks. Does Boost have a type of mutex that supports this functionality (assuming the C++11 mutex or lock types don't support this), or can this be done with conditional variables?
You cannot check whether other threads are waiting on a mutex.
If you want to give other threads their chance to run, just release the mutex. No need to know if someone is waiting. Then re-acquire as necessary.
Conditional variables are events. Use them if you want to wait until something happens. To check whether something has happened you need a regular (mutex-protected or atomic) variable.
you can not check if other threads are waiting on a mutex.
if you do need such functionality, you need to implement your own.
a mutex with use_count will suffice your need.
class my_mutex{
public:
my_mutex() {count=0;}
void lock() {count++; mtx.lock();}
void unlock() {count--; mtx.unlock();}
size_t get_waiting_threads() {return count>1?count-1:0;}
private:
atomic_ulong count;
mutex mtx;
};
if you need to finish task 1 and 2 before task 3 is executed, you should use conditional_variable instead of mutex.
If two threads are waiting on a lock, the thread that started waiting first is not guaranteed to be the thread that gets it first when it becomes available. So if you're a tight-looping thread who does something like
while(true):
mutex.lock()
print "got the lock; releasing it"
mutex.unlock()
You might think you're being polite to all the other threads waiting for the lock, but you're not, the system might just give you the lock over and over again without letting any of the other threads jump in, no matter how long they've been waiting.
Condition variables are a reasonable way to solve this problem.

Condition variable deadlock

I have a problem with a deadlock in my code related to the use of condition variables. This is more of a design question than a pure code question. I have no problem actually writing code once I understand the correct design. I have the following scenario:
Thread A waits on a condition variable.
Thread B calls notify_all, and thread A wakes up.
This is of course what I want to happen, and is what does happen when everything works as expected. But sometimes, I get the following scenario instead:
Thread A executes the code right before it begins to wait on the condition variable.
Thread B calls notify_all, thinking that thread A is waiting.
Thread A begins waiting on the condition variable, not realizing that thread B already told it to stop waiting. Deadlock.
What is the best way to resolve this? I can't think of a reliable way to check whether thread A is actually waiting, in order to know when I should call notify_all in thread B. Do I have to resort to timed_lock? I would hate to.
During the period just before Thread A waits on condition variable it must be holding a mutex. The easiest solution is to make sure that Thread B is holding the same mutex at the time it calls notify_all. So something like this:
std::mutex m;
std::condition_variable cv;
int the_condition = 0;
Thread A: {
std::unique_lock<std::mutex> lock(m);
do something
while (the_condition == 0) {
cv.wait(lock);
}
now the_condition != 0 and thread A has the mutex
do something else
} // releases the mutex;
Thread B: {
std::unique_lock<std::mutex> lock(m);
do something that makes the_condition != 0
cv.notify_all();
} // releases the mutex
This guarantees that Thread B only does the notify_all() either before Thread A acquires the mutex or while Thread A is waiting on the condition variable.
The other key here, though, is the while loop waiting for the_condition to become true. Once A has the mutex it should not be possible for any other thread to change the_condition until A has tested the_condition, found it false, and started waiting (thus releasing the mutex).
The point is: what you are really waiting for is for the value of the_condition to become non-zero, the std::condition_variable::notify_all is just telling you that thread B thinks thread A should wake up and retest.
A condition variable must always be associated with a mutex to avoid a race condition created by one thread preparing to wait and another thread which may signal the condition before the first thread actually waits on it resulting in a deadlock. The thread will be perpetually waiting for a signal that is never sent. Any mutex can be used, there is no explicit link between the mutex and the condition variable.