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.
Related
Looking at several videos and the documentation example, we unlock the mutex before calling the notify_all(). Will it be better to instead call it after?
The common way:
Inside the Notifier thread:
//prepare data for several worker-threads;
//and now, awaken the threads:
std::unique_lock<std::mutex> lock2(sharedMutex);
_threadsCanAwaken = true;
lock2.unlock();
_conditionVar.notify_all(); //awaken all the worker threads;
//wait until all threads completed;
//cleanup:
_threadsCanAwaken = false;
//prepare new batches once again, etc, etc
Inside one of the worker threads:
while(true){
// wait for the next batch:
std::unique_lock<std::mutex> lock1(sharedMutex);
_conditionVar.wait(lock1, [](){return _threadsCanAwaken});
lock1.unlock(); //let sibling worker-threads work on their part as well
//perform the final task
//signal the notifier that one more thread has completed;
//loop back and wait until the next task
}
Notice how the lock2 is unlocked before we notify the condition variable - should we instead unlock it after the notify_all() ?
Edit
From my comment below: My concern is that, what if the worker spuriously awakes, sees that the mutex is unlocked, super-quickly completes the task and loops back to the start of while. Now the slow-poke Notifier finally calls notify_all(), causing the worker to loop an additional time (excessive and undesired).
There are no advantages to unlocking the mutex before signaling the condition variable unless your implementation is unusual. There are two disadvantages to unlocking before signaling:
If you unlock before you signal, the signal may wake a thread that choose to block on the condition variable after you unlocked. This can lead to a deadlock if you use the same condition variable to signal more than one logical condition. This kind of bug is hard to create, hard to diagnose, and hard to understand. It is trivially avoided by always signaling before unlocking. This ensures that the change of shared state and the signal are an atomic operation and that race conditions and deadlocks are impossible.
There is a performance penalty for unlocking before signaling that is avoided by unlocking after signaling. If you signal before you unlock, a good implementation will know that your signal cannot possibly render any thread ready-to-run because the mutex is held by the calling thread and any thread affects by the condition variable necessarily cannot make forward progress without the mutex. This permits a significant optimization (often called "wait morphing") that is not possible if you unlock first.
So signal while holding the lock unless you have some unusual reason to do otherwise.
should we instead unlock it after the notify_all() ?
It is correct to do it either way but you may have different behavior in different situations. It is quite difficult to predict how it will affect performance of your program - I've seen both positive and negative effects for different applications. So it is better you profile your program and make decision on your particular situation based on profiling.
As mentioned here : cppreference.com
The notifying thread does not need to hold the lock on the same mutex
as the one held by the waiting thread(s); in fact doing so is a
pessimization, since the notified thread would immediately block
again, waiting for the notifying thread to release the lock.
That said, documentation for wait
At the moment of blocking the thread, the function automatically calls
lck.unlock(), allowing other locked threads to continue.
Once notified (explicitly, by some other thread), the function
unblocks and calls lck.lock(), leaving lck in the same state as when
the function was called. Then the function returns (notice that this
last mutex locking may block again the thread before returning).
so when notified wait will re-attempt to gain the lock and in that process it will get blocked again till original notifying thread releases the lock.
So I'll suggest that release the lock before calling notify. As done in example on cppreference.com and most importantly
Don't be Pessimistic.
David's answer seems to me wrong.
First, assuming the simple case of two threads, one waiting for the other on a condition variable, unlocking first by the notifier will not waken the other waiting thread, as the signal has not arrived. Then the notify call will immediately waken the waiting thread. You do not need any special optimizations.
On the other hand, signalling first has the potential of waking up a thread and making it sleep immediately again, as it cannot hold the lock—unless wait morphing is implemented.
Wait morphing does not exist in Linux at least, according to the answer under this StackOverflow question: Which OS / platforms implement wait morphing optimization?
The cppreference example also unlocks first before signalling: https://en.cppreference.com/w/cpp/thread/condition_variable/notify_all
It explicit says:
The notifying thread does not need to hold the lock on the same mutex as the one held by the waiting thread(s). Doing so may be a pessimization, since the notified thread would immediately block again, waiting for the notifying thread to release the lock, though some implementations recognize the pattern and do not attempt to wake up the thread that is notified under lock.
should we instead unlock it after the notify_all() ?
After reading several related posts, I've formed the opinion that it's purely a performance issue. If OS supports "wait morphing", unlock after; otherwise, unlock before.
I'm adding an answer here to augment that of #DavidSchwartz 's. Particularly, I'd like to clarify his point 1.
If you unlock before you signal, the signal may wake a thread that choose to block on the condition variable after you unlocked. This can lead to a deadlock if you use the same condition variable to signal more than one logical condition. This kind of bug is hard to create, hard to diagnose, and hard to understand. It is trivially avoided by always signaling before unlocking. This ensures that the change of shared state and the signal are an atomic operation and that race conditions and deadlocks are impossible.
The 1st thing I said is that, because it's a CV and not a Mutex, a better term for the so-called "deadlock" might be "sleep paralysis" - a mistake some programs make is that
a thread that's supposed to wake
went to sleep due to not rechecking the condition it's been waiting for before wait'ng again.
The 2nd thing is that, when waking some other thread(s),
the default choice should be broadcast/notify_all (broadcast is the POSIX term, which is equivalent to its C++ counterpart).
signal/notify is an optimized special case used for when there's only 1 other thread is waiting.
Finally 3rd, David is adamant that
it's better to unlock after notify,
because it can avoid the "deadlock" which I've been referring to as "sleep paralysis".
If it's unlock then notify, then there's a window where another thread (let's call this the "wrong" thread) may i.) acquire the mutex, ii.)going into wait, and iii.) wake up. The steps i. ii. and iii. happens too quickly, consumed the signal, leaving the intended (let's call it "correct") thread in sleep.
I discussed this extensively with David, he clarified that only when all 3 points are violated ( 1. condvar associated with several separate conditions and/or didn't check it before waiting again; 2. signal/notify only 1 thread when there're more than 1 other threads using the condvar; 3. unlock before notify creating a window for race condition ), the "sleep paralysis" would occur.
Finally, my recommendation is that, point 1 and 2 are essential for correctness of the program, and fixing issues associated with 1 and 2 should be prioritized over 3, which should only be a augmentative "last resort".
For the purpose of providing reference, manpage for signal/broadcast and wait contains some info from version 3 of Single Unix Specification that gave some explanations on point 1 and 2, and partly 3. Although specified for POSIX/Unix/Linux in C, it's concepts are applicable to C++.
As of this writing (2023-01-31), the 2018 edition of version 4 of Single Unix Specification is released, and the drafting of version 5 is underway.
i want to know how it is possible to wait for a work to done and then continue and create new one
while(!stop)
{
CreateWork();
waitForWorkToDone();
}
wait must not block calling thread
how i can achive this?
To achieve this, you can rely on the operating system providing a facility to block until notified with or without a timeout. Thus, your thread correctly does not use unnecessary CPU cycles by performing a busy wait, but is still able to respond to program state changes. With POSIX threads, you can use a condition timed wait. I'll illustrate with the boost implementation, but the concept extends generally.
do
{
boost::unique_lock<boost::mutex> lock(state_change_mutex);
boost::system_time const timeout = boost::get_system_time() + boost::posix_time::seconds(5);
state_change_cond.timed_wait(lock,timeout);
...
} while(!done);
Overall this thread will loop until the done sentinel value becomes true. Other threads can signal this thread by calling
state_change_cond.notify_all();
Or in this example if no signal happens in 5 seconds then the thread wakes up by itself.
Note that condition variables require locking by mutexes. This is to guarantee that the thread is awoken atomically and that it will behave correctly in a mutually exclusive section as inter-thread signaling implicitly is.
How about Creating a Signal. Create a handler that creates CreateWork() and signals when the job is done! Just a Suggestion
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.
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 learning multi-threading and for the sake of understanding I have wriiten a small function using multithreading...it works fine.But I just want to know if that thread is safe to use,did I followed the correct rule.
void CThreadingEx4Dlg::OnBnClickedOk()
{
//in thread1 100 elements are copied to myShiftArray(which is a CStringArray)
thread1 = AfxBeginThread((AFX_THREADPROC)MyThreadFunction1,this);
WaitForSingleObject(thread1->m_hThread,INFINITE);
//thread2 waits for thread1 to finish because thread2 is going to make use of myShiftArray(in which thread1 processes it first)
thread2 = AfxBeginThread((AFX_THREADPROC)MyThreadFunction2,this);
thread3 = AfxBeginThread((AFX_THREADPROC)MyThreadFunction3,this);
}
UINT MyThreadFunction1(LPARAM lparam)
{
CThreadingEx4Dlg* pthis = (CThreadingEx4Dlg*)lparam;
pthis->MyFunction(0,100);
return 0;
}
UINT MyThreadFunction2(LPARAM lparam)
{
CThreadingEx4Dlg* pthis = (CThreadingEx4Dlg*)lparam;
pthis->MyCommonFunction(0,20);
return 0;
}
UINT MyThreadFunction3(LPARAM lparam)
{
CThreadingEx4Dlg* pthis = (CThreadingEx4Dlg*)lparam;
WaitForSingleObject(pthis->thread3->m_hThread,INFINITE);
//here thread3 waits for thread 2 to finish so that thread can continue
pthis->MyCommonFunction(21,40);
return 0;
}
void CThreadingEx4Dlg::MyFunction(int minCount,int maxCount)
{
for(int i=minCount;i<maxCount;i++)
{
//assume myArray is a CStringArray and it has 100 elemnts added to it.
//myShiftArray is a CStringArray -public to the class
CString temp;
temp = myArray.GetAt(i);
myShiftArray.Add(temp);
}
}
void CThreadingEx4Dlg::MyCommonFunction(int min,int max)
{
for(int i = min;i < max;i++)
{
CSingleLock myLock(&myCS,TRUE);
CString temp;
temp = myShiftArray.GetAt(i);
//threadArray is CStringArray-public to the class
threadArray.Add(temp);
}
myEvent.PulseEvent();
}
Which function do you intend to be "thread-safe"?
I think that the term should be applied to your CommonFunction. This is a function that you intend to be called be several (two in this first case) threads.
I think your code has a rule on the lines of:
Thread 2 do some work
meanwhile Thread 3 wait until Thread 2 finishes then you do some work
In fact your code has
WaitForSingleObject(pthis->thread3->m_hThread,INFINITE);
maybe waits for the wrong thread?
But back to thread safety. Where is the policing of the safety? It's in the control logic of your threads. Suppose you had lots of threads, how would you extend what you've written? You have lots of logic of the kind:
if thread a has finished and thread b has finished ...
Really hard to get right and maintain. Instead you need to make CommonFunction truly thread safe, that is it needs to tolerate being called by several threads at the same time.
In this case you might do that by putting some kind of mutex around the critical part of the code, which perhaps in this case is the whole function - it's not clear whether you intend to keep the items you copy together or whether you mind if the values are interleaved.
In the latter case the only question is whether access to myArray and myShiftArray are thread safe collections
temp = myArray.GetAt(i);
myShiftArray.Add(temp);
all your other variables are local, on the stack so owned by current threads - so you just need to consult the documentation for those collections to determine if they can safely be called by separate threads.
As I've pointed out before what you are doing is entirely pointless you may as well not use threads as you fire a thread off and then wait for the thread to complete before doing anything further.
You give precious little information about your CEvent but your WaitForSingleObjects are waiting for the thread to enter a signalled state (ie for them to exit).
As MyCommonFunction is where the actual potentially thread un-safe thing occurs you have correctly critical sectioned the area, however, threads 2 and threads 3 don't run concurrently. Remove the WaitForSingleObject from MyThreadFunction3 and then you will have both running concurrently in a thread-safe manner, thanks to the critical section.
That said its still a tad pointless as both threads are going to spend most of their time waiting for the critical section to come free. In general you want to structure threads so that there is precious little they need to hit critical sections for and then, when they hit a critical section, hit it only for a very short time (ie not the vast majority of the function's processing time).
Edit:
A Critical section works by saying I'm holding this critical section anything else that wants it has to wait. This means that Thread 1 enters the critical section and begins to do what it needs to do. Thread 2 then comes along and says "I want to use the critical section". The kernel tell its "Thread 1 is using the critical section you have to wait your turn". Thread 3 comes along and gets told the same thing. Threads 2 and 3 are now in a wait state waiting for that critical section to come free. When Thread 1 finishes with the critical section both Threads 2 and 3 race to see who gets to hold the critical section first and when one obtains it the other has to continue waiting.
Now in your example above there would be so much waiting for critical sections it is possible that Thread 1 can be in the critical section and Thread 2 waiting and before Thread 2 has been given the chance to enter the critical section Thread 1 has looped back round and re-entered it. This means that Thread 1 could end up doing all its work before Thread 2 ever gets a chance to enter the critical section. Therefore keeping the amount of work done in the critical section compared to the rest of the loop/function as low as possible will aid the Threads running simultaneously. In your example one thread will ALWAYS be waiting for the other thread and hence just doing it serially may actually be faster as you have no kernel threading overheads.
ie the more you avoid CriticalSections the less time lost for threads waiting for each other. They are necessary, however, as you NEED to make sure that 2 threads don't try and operate on the same object at the same time. Certain in-built objects are "atomic" which can aid you on this but for non-atomic operations a critical section is a must.
An Event is a different sort of synchronisation object. Basically an event is an object that can be one of 2 states. Signalled or not-signalled. If you WaitForSingleObject on a "not-signalled" event then the thread will be put to sleep until it enters a signalled state.
This can be useful when you have a thread that MUST wait for another thread to complete something. In general though you want to avoid using such synchronisation objects as much as possible as it destroys the parallel-ness of your code.
Personally I use them when I have a worker thread waiting for when it needs to do something. The Thread sits in a wait state most of its time and then when some background processing is required I signal the event. The thread then jumps into life and does what it needs to do before looping back round and re-entering the wait state. You can also mark a variable as indicating that the object needs to exit. This way you can set an exit variable to true and then signal the waiting thread. The waiting thread wakes up and says "I should exit" and then exits. Be warned though that you "may" need a memory barrier that says make sure the exit variable is set before the event is woken up otherwise the compiler might re-order the operations. This could end up leaving your thread waking up finding out that the exit variable isn't set doing its thing and then going back to sleep. However the thread that originally sent the signal now assumes the thread has exited when it actually hasn't.
Whoever said multi-threading was easy eh? ;)
It looks like this is going to work because the threads aren't going to do any work concurrently. If you change the code to make the threads perform work at the same time, you will need to put mutexes (in MFC you can use CCriticalSection for that) around the code that accesses data members which are shared between the threads.