I am new to conditional variables and get deadlock if not using pthread_cond_broadcast().
#include <iostream>
#include <pthread.h>
pthread_mutex_t m_mut = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
bool ready = false;
void* print_id (void *ptr )
{
pthread_mutex_lock(&m_mut);
while (!ready) pthread_cond_wait(&cv, &m_mut);
int id = *((int*) ptr);
std::cout << "thread " << id << '\n';
pthread_mutex_unlock(&m_mut);
pthread_exit(0);
return NULL;
}
condition is changed here!
void go() {
pthread_mutex_lock(&m_mut);
ready = true;
pthread_mutex_unlock(&m_mut);
pthread_cond_signal(&cv);
}
It can work if I change the last line of go() to pthread_cond_broadcast(&cv);
int main ()
{
pthread_t threads[10];
// spawn 10 threads:
for (int i=0; i<10; i++)
pthread_create(&threads[i], NULL, print_id, (void *) new int(i));
go();
for (int i=0; i<10; i++) pthread_join(threads[i], NULL);
pthread_mutex_destroy(&m_mut);
pthread_cond_destroy(&cv);
return 0;
}
The expected answer (arbitrary order) is
thread 0
....
thread 9
However, on my machine (ubuntu), it prints nothing.
Could anyone tell me the reason? Thanks.
From the manual page (with my emphasis):
pthread_cond_signal restarts one of the threads that are waiting on the condition variable cond. If no threads are waiting on cond, nothing happens. If several threads are waiting on cond, exactly one is restarted, but it is not specified which.
pthread_cond_broadcast restarts all the threads that are waiting on the condition variable cond. Nothing happens if no threads are waiting on cond.
Each of your ten threads is waiting on the same condition. You only call go() once - that's from main(). This calls pthread_cond_signal, which will only signal one of the threads (an arbitrary one). All the others will still be waiting, and hence the pthread_join hangs as they won't terminate. When you switch it to pthread_cond_broadcast, all of the threads are triggered.
Related
I am trying to synchronize one main thread with N children threads. After some reading, I used condition_variable and unique_lock. However, I always get the errors condition_variable::wait: mutex not locked: Operation not permitted or unique_lock::unlock: not locked: Operation not permitted, in OS X. In Linux, I get Operation not permitted only.
To be clearer: my goal is to get a sequence of prints:
main thread, passing to 0
thread 0, passing back to main
main thread, passing to 0
thread 0, passing back to main
...
for each of the four threads.
I adapted the code from the example in http://en.cppreference.com/w/cpp/thread/condition_variable. This example uses unlock after wait, and it works wonderfully with only one thread other than main (N=1). But when adapted to work with N>1 threads, the error above happens.
Yam Marcovic said in the comments that I should not use unlock. But then, why does the cppreference example use it? And why does it work well with one main and one other threads?
Here is the code:
#include <cstdio>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
constexpr int N_THREADS = 4;
constexpr int N_ITER = 10;
bool in_main[N_THREADS] = {false};
void fun(mutex *const mtx, condition_variable *const cv, int tid){
for(int i=0; i<N_ITER; i++) {
unique_lock<mutex> lk(*mtx);
// Wait until in_main[tid] is false
cv->wait(lk, [=]{return !in_main[tid];});
// After the wait we own the lock on mtx, which is in lk
printf("thread %d, passing back to main\n", tid);
in_main[tid] = true;
lk.unlock(); // error here, but example uses unlock
cv->notify_one();
}
}
int main(int argc, char *argv[]) {
// We are going to create N_THREADS threads. Create mutexes and
// condition_variables for all of them.
mutex mtx[N_THREADS];
condition_variable cv[N_THREADS];
thread t[N_THREADS];
// Create N_THREADS unique_locks for using the condition_variable with each
// thread
unique_lock<mutex> lk[N_THREADS];
for(int i=0; i<N_THREADS; i++) {
lk[i] = unique_lock<mutex>(mtx[i]);
// Create the new thread, giving it its thread id, the mutex and the
// condition_variable,
t[i] = thread(fun, &mtx[i], &cv[i], i);
}
for(int i=0; i < N_ITER*N_THREADS; i++) {
int tid=i % N_THREADS; // Thread id
// Wait until in_main[tid] is true
cv[tid].wait(lk[tid], [=]{return in_main[tid];});
// After the wait we own the lock on mtx[tid], which is in lk[tid]
printf("main thread, passing to %d\n", tid);
in_main[tid] = false;
lk[tid].unlock(); // error here, but example uses unlock
cv[tid].notify_one();
}
for(int i=0; i<N_THREADS; i++)
t[i].join();
return 0;
}
Sample output:
thread 0, passing back to main
main thread, passing to 0
thread 1, passing back to main
thread 0, passing back to main
main thread, passing to 1
thread 2, passing back to main
thread 1, passing back to main
main thread, passing to 2
thread 2, passing back to main
thread 3, passing back to main
main thread, passing to 3
main thread, passing to 0
thread 3, passing back to main
libc++abi.dylib: terminating with uncaught exception of type std::__1::system_error: unique_lock::unlock: not locked: Operation not permitted
Abort trap: 6
you are trying to unlock your mutexes many times! look at the code carefully:
for(int i=0; i < N_ITER*N_THREADS; i++) {
int tid=i % N_THREADS; // Thread id
where N_ITER is 10 and N_THREADS is 4 always, because they are constexpr
we get:
for(int i=0; i < 40; i++) {
int tid=i % 4; // Thread id
so, when i = 0 the mutex in lk[0] is unlocked, and then when i=4 then tid = 4%4 so again tid = 0 and you are unlocking it again! std::system_error is thrown in this case.
plus, why are all of these C-Pointers anyway? it's not like anyof them can be null at any time.. switch to references..
also, usually when dealing with array indexes the convention is to use size_t and not int.
I found what the problem is. This question Using std::mutex, std::condition_variable and std::unique_lock helped me.
Constructing a unique_lock is acquiring the unique_lock too. So it must be done inside the loop, just before calling wait. The function fun looks the same, but main now looks like this:
int main(int argc, char *argv[]) {
// We are going to create N_THREADS threads. Create mutexes and
// condition_variables for all of them.
mutex mtx[N_THREADS];
condition_variable cv[N_THREADS];
thread t[N_THREADS];
// Create N_THREADS unique_locks for using the condition_variable with each
// thread
for(int i=0; i<N_THREADS; i++) {
// Create the new thread, giving it its thread id, the mutex and the
// condition_variable,
t[i] = thread(fun, &mtx[i], &cv[i], i);
// DO NOT construct, therefore acquire, a unique_lock
}
for(int i=0; i < N_ITER*N_THREADS; i++) {
int tid=i % N_THREADS; // Thread id
// Acquire the unique_lock here
unique_lock<mutex> lk(mtx[tid]);
// Wait until in_main[tid] is true
cv[tid].wait(lk, [=]{return in_main[tid];});
// After the wait we own the lock on mtx[tid], which is in lk[tid]
printf("main thread, passing to %d\n", tid);
in_main[tid] = false;
lk.unlock(); // error here, but example uses unlock
cv[tid].notify_one();
}
for(int i=0; i<N_THREADS; i++)
t[i].join();
return 0;
}
The only difference is that the unique_lock is constructed inside the loop.
#include<pthread.h>
#include<stdio.h>
int num_threads=3;
int state=0;
pthread_cond_t cond;
pthread_mutex_t mutex;
void* threadA(void* args) {
int i;
for(i=0; i<5; i++){
pthread_mutex_lock(&mutex);
while(state == 1 || state == 2) pthread_cond_wait(&cond,&mutex);
printf("Thread A\n");
state = (state+1)%num_threads;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
}
void* threadB(void* args) {
int i;
for(i=0; i<5; i++){
pthread_mutex_lock(&mutex);
while(state == 0 || state == 2)pthread_cond_wait(&cond,&mutex);
printf("Thread B\n");
state = (state+1)%num_threads;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
}
void* threadC(void* args) {
int i;
for(i=0; i<5; i++){
pthread_mutex_lock(&mutex);
while(state == 1 || state == 0) pthread_cond_wait(&cond,&mutex);
printf("Thread C\n\n");
state = (state+1)%num_threads;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
}
int main() {
pthread_t tid[3];
pthread_cond_init(&cond,NULL);
pthread_mutex_init(&mutex,NULL);
pthread_create(&tid[0],NULL,threadA,NULL);
pthread_create(&tid[1],NULL,threadB,NULL);
pthread_create(&tid[2],NULL,threadC,NULL);
return 0;
}
QUESTION: With the above code, I wish to print
threaA threadB threadC sequentially 5 times.
But the answer is undeterministic. While the order
of threads is maintained, answers are not printed 5 times.
Please help!!!
As #mch mentioned in the comment, you need to wait for the threads to finish before allowing the main() function to return:
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
pthread_join(tid[2], NULL);
Now, after you add the joins above to the end of main(), your program will most often hang. This happens because the pthread_cond_signal() doesn't wake up all threads waiting on that condition variable. If the wrong thread is woke up (e.g. threadC signals the condition, but the thread that gets notified is not threadA), then all threads will be waiting on the condition and there will be nobody to signal that condition.
To fix this, you need to make sure all threads are woke up each time and let each thread decide on it's own if it is its turn or not (by that while(state...) pthread_cond_wait(...);). To do this, you can replace the calls to pthread_cond_signal() with calls to pthread_cond_broadcast(), which unblocks all threads currently blocked on that condition.
I'm trying to have pthreads run multiple instances of a function at once, to increase runtime speed and efficiency. My code is supposed to spawn threads and keep them open for whenever there is more items in the queue. Then those threads are supposed to do 'something'. The code is supposed to ask to "continue?" when there are no more items in the queue, and if I type "yes", then items should be added to the queue and the threads should continue doing 'something'. This is what I have so far,
# include <iostream>
# include <string>
# include <pthread.h>
# include <queue>
using namespace std;
# define NUM_THREADS 100
int main ( );
queue<int> testQueue;
void *checkEmpty(void* arg);
void *playQueue(void* arg);
void matrix_exponential_test01 ( );
void matrix_exponential_test02 ( );
pthread_mutex_t queueLock;
pthread_cond_t queue_cv;
int main()
{
pthread_t threads[NUM_THREADS+1];
pthread_mutex_init(&queueLock, NULL);
pthread_cond_init (&queue_cv, NULL);
for( int i=0; i < NUM_THREADS; i++ )
{
pthread_create(&threads[i], NULL, playQueue, (void*)NULL);
}
string cont = "yes";
do
{
cout<<"Continue? ";
getline(cin, cont);
pthread_mutex_lock (&queueLock);
for(int z=0; z<10; z++)
{
testQueue.push(1);
}
pthread_mutex_unlock (&queueLock);
}while(cont.compare("yes"));
pthread_mutex_destroy(&queueLock);
pthread_cond_destroy(&queue_cv);
pthread_exit(NULL);
return 0;
}
void* checkEmpty(void* arg)
{
while(true)
{
pthread_mutex_lock (&queueLock);
if(!testQueue.empty()){
pthread_cond_signal(&queue_cv);}
pthread_mutex_unlock (&queueLock);
}
pthread_exit(NULL);
}
void* playQueue(void* arg)
{
while(true)
{
pthread_cond_wait(&queue_cv, &queueLock);
pthread_mutex_lock (&queueLock);
if(!testQueue.empty())
{
testQueue.pop();
cout<<testQueue.size()<<endl;
}
pthread_mutex_unlock (&queueLock);
}
pthread_exit(NULL);
}
So my issue lies with the fact that the code goes into deadlock, and I cant figure out where the issue occurs. I'm no veteran with multithreading so its very easy for me to make a mistake here. I am also running this on Windows.
You have two issues :
The condition variable queue_cv is never signaled. You can signal it with pthread_cond_signal after having pushed elements in the queue : pthread_cond_signal(&queue_cv);
In playQueue, you try to acquire the lock after returning from pthread_cond_wait : since your mutex is not reentrant, this is undefined behavior (this is likely the source of your deadlock). Just remove the pthread_mutex_lock (&queueLock);
Note:
I'm not sure what is it's true purpose, but the checkEmpty() method is never called
Because of the MAXIMUM_WAIT_OBJECTS restriction of WaitForMultipleObjects function, I tried to write my own "wait for threads" function but didn't get it work. Can you give me a hint, how to do it?
This is my "wait for threads" function:
void WaitForThreads(std::set<HANDLE>& handles)
{
for (int i = 0; i < SECONDSTOWAIT; i++)
{
// erase idiom
for (std::set<HANDLE>::iterator it = handles.begin();
it != handles.end();)
{
if (WaitForSingleObject(*it, 0) == WAIT_OBJECT_0)
handles.erase(it++);
else
++it;
}
if (!handles.size())
// all threads terminated
return;
Sleep(1000);
}
// handles.size() threads still running
handles.clear();
}
As long as the thread runs WaitForSingleObject returns WAIT_TIMEOUT but when the thread terminates the return value is WAIT_FAILED instead of WAIT_OBJECT_0. I guess the thread handle is no longer valid because GetLastError returns ERROR_INVALID_HANDLE.
The MSDN suggests following solutions:
Create a thread to wait on MAXIMUM_WAIT_OBJECTS handles, then wait on that thread plus the other handles. Use this technique to break the handles into groups of MAXIMUM_WAIT_OBJECTS.
Call RegisterWaitForSingleObject to wait on each handle. A wait thread from the thread pool waits on MAXIMUM_WAIT_OBJECTS registered objects and assigns a worker thread after the object is signaled or the time-out interval expires.
But it seems to me that both are too much effort.
Edit:
The threads are created with the MFC function AfxBeginThread. The returned CWinThread pointer is only used to get the associated handle.
CWinThread* thread = AfxBeginThread(LANAbfrage, par);
if ((*thread).m_hThread)
{
threads.insert((*thread).m_hThread);
helper::setStatus("%u LAN Threads active", threads.size());
}
else
theVar->TraceN("Error: Can not create thread");
But it seems to me that both are too much effort.
If you want it to work with wait handles, that's what you'll have to do. But if all you need is something that will block until all of the threads have finished, you can use a Semaphore or perhaps a Synchronization Barrier.
With the answer from Jim Mischel I found a solution. Semaphore Objects can solve two issues:
Waiting for all threads
Limiting the number of running threads
This is a small, self contained example:
#include <iostream>
#include <vector>
#include <windows.h>
static const LONG SEMCOUNT = 3;
DWORD CALLBACK ThreadProc(void* vptr)
{
HANDLE* sem = (HANDLE*)vptr;
Sleep(10000);
ReleaseSemaphore(*sem, 1, NULL);
return 0;
}
int main()
{
HANDLE semh = CreateSemaphore(NULL, SEMCOUNT, SEMCOUNT, 0);
// create 10 threads, but only SEMCOUNT threads run at once
for (int i = 0; i < 10; i++)
{
DWORD id;
WaitForSingleObject(semh, INFINITE);
HANDLE h = CreateThread(NULL, 0, ThreadProc, (void*)&semh, 0, &id);
if (!h)
CloseHandle(h);
}
// wait until all threads have released the semaphore
for (LONG j = 0; j < SEMCOUNT; j++)
{
WaitForSingleObject(semh, INFINITE);
std::cout << "Semaphore count = " << j << std::endl;
}
std::cout << "All threads terminated" << std::endl;
return 0;
}
I am new to multithreading and hence started with a small program. The job expected from the program is, to print integers one after the other by means of two threads in such a way that one thread should print one number and the other thread should print the next number and this process should continue till a maximum number defined.
For this I wrote a small program and iam facing dead lock. I tried to find mutex owner using gdb but it;s just printing $3 = 2 when I execute print mutex command.
Here is the source code:
#include <iostream>
#include <fstream>
#include <pthread.h>
#include <signal.h>
const int MAX_NUM = 13;
pthread_cond_t cond[1] = {PTHREAD_COND_INITIALIZER,};
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int Count = 0;
using namespace std;
void* thread1(void*)
{
do {
cout<<"inside thread 1 abt to acquire lock"<<endl;
// Increment counter in thread1
pthread_mutex_lock(&mutex);
cout<<"inside thread 1 blocked"<<endl;
pthread_cond_wait(&cond[0],&mutex);
cout<<"after pthread_cond_wait in thread1"<<endl;
pthread_cond_signal(&cond[1]);
if(Count < MAX_NUM)
{
Count++;
pthread_mutex_unlock(&mutex);
cout<<"Printing from thread 1"<<endl;
cout<<Count<<endl;
}
else
{
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
}while(1);
}
void* thread2(void*)
{
do{
cout<<"inside thread 2 abt to acquire lock"<<endl;
pthread_mutex_lock(&mutex);
cout<<"inside thread 2 blocked"<<endl;
pthread_cond_wait(&cond[1],&mutex);
// Increment counter in thread2
pthread_cond_signal(&cond[0]);
if(Count < MAX_NUM)
{
Count++;
pthread_mutex_unlock(&mutex);
cout<<"Printing from thread 2"<<endl;
cout<<Count<<endl;
}
else
{
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
}while(1);
}
int main()
{
pthread_t t[2];
void* (*fun[2])(void*);
fun[0]=thread1;
fun[1]=thread2;
for (int i =0 ; i < 2; ++i)
{
pthread_create(&t[i],NULL,fun[i],NULL);
}
cout<<"threads created"<<endl;
pthread_cond_signal(&cond[0]);
cout<<"In main after sending signal"<<endl;
pthread_join(t[0],NULL);
pthread_join(t[1],NULL);
pthread_exit(NULL);
}
Output is:
inside thread 1 abt to acquire lock
inside thread 1 blocked
inside thread 2 abt to acquire lock
inside thread 2 blocked
threads created
In main after sending signal
I expected main() thread to send a signal to thread 1 which does it's job (i.e. updating counter) and then passes signal to thread 2 which does it's job (i.e. updating counter) and passes signal to thread 1. This process should continue until max number is reached. If max number is reached each process unlocks mutex and exits gracefully.
Please help me. I really tried a lot nothing worked.
the line
pthread_cond_t cond[1] = {PTHREAD_COND_INITIALIZER,};
defines an array of size 1, but later on you use cond[1], the second entry in the array, which is undefined. Did you mean
pthread_cond_t cond[2] = {PTHREAD_COND_INITIALIZER,PTHREAD_COND_INITIALIZER};
This looks like an unlucky typo. (Due to the preceeding MAX_NUM = 13?)
In addition to #TooTone's observation you need to understand one aspect of how condition variables work. If you signal a condition variable when no thread is blocked on it nothing will happen. The condition variable has no memory, so if a little bit later a thread blocks on in it will stay locked until the condition is signaled again.
Your main function signals cond[0] right after it started the threads, so it is possible that the threads haven't reached their blocking point yet. Or if they are blocked then it can happen that when one thread signals the other one that other one isn't blocked. So after you fix your condition variable array you will see that the test runs a bit more, but eventually deadlocks again.
I was able to make it work using a quick & dirty trick of introducing delays before signaling the condition variables. This gives the threads time to reach their blocking points before the signaling happens. Here is the modified code:
const int MAX_NUM = 13;
pthread_cond_t cond[2] = {PTHREAD_COND_INITIALIZER,PTHREAD_COND_INITIALIZER};
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int Count = 0;
using namespace std;
void* thread1(void*)
{
do {
cout<<"inside thread 1 abt to acquire lock"<<endl;
// Increment counter in thread1
pthread_mutex_lock(&mutex);
cout<<"inside thread 1 blocked"<<endl;
pthread_cond_wait(&cond[0],&mutex);
cout<<"after pthread_cond_wait in thread1"<<endl;
if(Count < MAX_NUM)
{
Count++;
pthread_mutex_unlock(&mutex);
cout<<"Printing from thread 1"<<endl;
cout<<Count<<endl;
usleep(1000000);
pthread_cond_signal(&cond[1]);
}
else
{
pthread_mutex_unlock(&mutex);
usleep(1000000);
pthread_cond_signal(&cond[1]);
pthread_exit(NULL);
}
}while(1);
}
void* thread2(void*)
{
do{
cout<<"inside thread 2 abt to acquire lock"<<endl;
pthread_mutex_lock(&mutex);
cout<<"inside thread 2 blocked"<<endl;
pthread_cond_wait(&cond[1],&mutex);
// Increment counter in thread2
if(Count < MAX_NUM)
{
Count++;
pthread_mutex_unlock(&mutex);
cout<<"Printing from thread 2"<<endl;
cout<<Count<<endl;
usleep(1000000);
pthread_cond_signal(&cond[0]);
}
else
{
pthread_mutex_unlock(&mutex);
usleep(1000000);
pthread_cond_signal(&cond[0]);
pthread_exit(NULL);
}
}while(1);
}
int main()
{
pthread_t t[2];
void* (*fun[2])(void*);
fun[0]=thread1;
fun[1]=thread2;
for (int i =0 ; i < 2; ++i)
{
pthread_create(&t[i],NULL,fun[i],NULL);
}
cout<<"threads created"<<endl;
usleep(1000000);
pthread_cond_signal(&cond[0]);
cout<<"In main after sending signal"<<endl;
pthread_join(t[0],NULL);
pthread_join(t[1],NULL);
pthread_exit(NULL);
}
Using condition variables for this kind of thing isn't the best idea. Semaphores are better suited to the task because those do have memory and remember their signaled state even if nobody is waiting on them when they are signaled.