Multiple threads attempting to lock - c++

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.

Related

How do threads wait when condition_variable wait function is called?

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.

Giving lock to certain thread

Is there a way to give a certain thread priority if multiple threads try to aquire the same mutex at one time
For example you have 2 threads both started at the same time and they sleep then try to acquire lock
In main thread
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
pthread_t thrd1, thrd2;
pthread_create( &thrd1, NULL, someFunc, NULL);
pthread_create( &thrd2, NULL, someFunc, NULL);
and someFunc() would have
usleep(1000);
pthread_mutex_lock(&mut);
I thought this had to do with threading priority but that appears to be a different topic.
Is there a way to guarantee thread 2 got the lock on mut first?
Your problem is underspecified, because you do not provide any parameters on use case or how you have determined a choice is to be made. You seem to believe that priority alone will be sufficient to get you the behavior you want, but that is a fallacy.
Priority alone is insufficient.
Priority alone does not let a higher priority thread wrest control of a mutex away from a lower priority thread that has acquired a lock. The lower priority thread must voluntarily yield the lock for the sake of safely handling the protected critical section. If the higher priority thread was allowed to yank the mutex away from the lower priority thread, the state in the critical section may be left inconsistent by the lower priority thread, and this could cause problems for the higher priority thread.
Here are some options.
Option 1: Start thread 2 first.
This is the simplest solution. Just launch thread 2 first, and let it notify the main thread when it has acquired the lock. Then, the main thread can start thread 1.
If you really just want each thread to figure it out without intervention from the main thread, then you have the specify what you mean by "guarantee thread 2 got the lock first". If thread 1 truly wakes up first, and goes for the lock without any contention, what do you expect it to do about that? And, how does thread 1 know that it is thread 1 and not thread 2?
Option 2: Why care about which thread is which?
If there is no specific reason that thread 2 is thread 2, then you could just let which ever thread gets the lock first do whatever it is that thread 2 is supposed to do, and the subsequent thread does whatever thread 1 is supposed to do.
This reduces the problem to only needing to know if any thread has gone yet or not. However, if you really do care that thread 2 is supposed to go first, then you still need to handle the case that thread 1 gets the lock out of turn. So, it needs to somehow know that it is thread 1, and it needs to know somehow that thread 2 has not done its thing yet.
Option 3: Make thread 1 wait for thread 2 (somehow).
When the thread starts, it first determines which thread it is. If it is thread 1, it waits for an indication from thread 2 that it can acquire the lock. If it is thread 2, it first acquires the lock, then delivers an indication to thread 1 that it may acquire the lock.
Options 1 and 3 have one thread notifying another thread. There are many variations on how this notification can be delivered. You could use a semaphore, or a condition wait, or a pipe, or even a spin lock. There are many other options, it just depends on what you believe is the right choice for your application.

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.

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

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.

Non-recursive mutex ownership

I read this answer on SO:
Because the recursive mutex has a sense of ownership, the thread that grabs the mutex must be the same thread that releases the mutex. In the case of non-recursive mutexes, there is no sense of ownership and any thread can usually release the mutex no matter which thread originally took the mutex.
I'm confused by the last statement. Can one thread lock a mutex and another different thread unlock that mutex? I thought that same thread should be the only one able to unlock the mutex? Or is there any specific mutex that allows this? I hope someone can clarify.
Non-recursive mutex
Most mutexes are (or at least should be) non-recursive. A mutex is an object which can be acquired or released atomically, which allows data which is shared between multiple threads to be protected against race conditions, data corruption, and other nasty things.
A single mutex should only ever be acquired once by a single thread within the same call chain. Attempting to acquire (or hold) the same mutex twice, within the same thread context, should be considered an invalid scenario, and should be handled appropriately (usually via an ASSERT as you are breaking a fundamental contract of your code).
Recursive mutex
This should be considered a code smell, or a hack. The only way in which a recursive mutex differs from a standard mutex is that a recursive mutex can be acquired multiple times by the same thread.
The root cause of the need for a recursive mutex is lack of ownership and no clear purpose or delineation between classes. For example, your code may call into another class, which then calls back into your class. The starting class could then try to acquire the same mutex again, and because you want to avoid a crash, you implement this as a recursive mutex.
This kind of topsy-turvy class hierarchy can lead to all sorts of headaches, and a recursive mutex provides only a band-aid solution for a more fundamental architectural problem.
Regardless of the mutex type, it should always be the same thread which acquires and releases the same mutex. The general pattern that you use in code is something like this:
Thread 1
Acquire mutex A
// Modify or read shared data
Release mutex A
Thread 2
Attempt to acquire mutex A
Block as thread 1 has mutex A
When thread 1 has released mutex A, acquire it
// Modify or read shared data
Release mutex A
It gets more complicated when you have multiple mutexes that can be acquired simultaneously (say, mutex A and B). There is the risk that you'll run into a deadlock situation like this:
Thread 1
Acquire mutex A
// Access some data...
*** Context switch to thread 2 ***
Thread 2
Acquire mutex B
// Access some data
*** Context switch to thread 1 ***
Attempt to acquire mutex B
Wait for thread 2 to release mutex B
*** Context switch to thread 2 ***
Attempt to acquire mutex A
Wait for thread 1 to release mutex A
*** DEADLOCK ***
We now have a situation where each thread is waiting for the other thread to release the other lock -- this is known as the ABBA deadlock pattern.
To prevent this situation, it is important that each thread always acquires the mutexes in the same order (e.g. always A, then B).
Recursive mutexes are thread-specific by design (the same thread locking again = recursion, another thread locking meanwhile = block). Regular mutexes do not have this design and thus they can in fact be locked and unlocked in different threads.
I think this covers all your questions. Straight from linux man pages for pthreads:
If the mutex type is PTHREAD_MUTEX_NORMAL, deadlock detection shall not be provided. Attempting to relock the mutex causes deadlock. If a thread
attempts to unlock a mutex that it has not locked or a mutex which is unlocked, undefined behavior results.
If the mutex type is PTHREAD_MUTEX_ERRORCHECK, then error checking shall be provided. If a thread attempts to relock a mutex that it has already
locked, an error shall be returned. If a thread attempts to unlock a mutex that it has not locked or a mutex which is unlocked, an error shall be
returned.
If the mutex type is PTHREAD_MUTEX_RECURSIVE, then the mutex shall maintain the concept of a lock count. When a thread successfully acquires a
mutex for the first time, the lock count shall be set to one. Every time a thread relocks this mutex, the lock count shall be incremented by one.
Each time the thread unlocks the mutex, the lock count shall be decremented by one. When the lock count reaches zero, the mutex shall become
available for other threads to acquire. If a thread attempts to unlock a mutex that it has not locked or a mutex which is unlocked, an error shall
be returned.
If the mutex type is PTHREAD_MUTEX_DEFAULT, attempting to recursively lock the mutex results in undefined behavior. Attempting to unlock the mutex
if it was not locked by the calling thread results in undefined behavior. Attempting to unlock the mutex if it is not locked results in undefined
behavior.