I wrote a wrote a program and it doesn’t work as I expect it to.
I have two threads: thread triggers func and anotherThread triggers anotherFunc. What I wanted to do is when cont reaches value 10 in func, anotherThread to be triggered using pthread_cond_wait and pthread_cond_signal. The strange thing is everything works fine if i uncomment the sleep(1) line. I’m new to threads and I was following the tutorial here and if I comment the sleep line in their example it breaks as well.
My question is how can I make this work without any sleep() calls? And what happens if in my code both func reaches pthread_mutex_lock after anotherFunc? How can I control these things? This is my code:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t myMutex;
pthread_cond_t cond;
pthread_attr_t attr;
int cont;
void *func(void*)
{
printf("func\n");
for(int i = 0; i < 20; i++)
{
pthread_mutex_lock(&myMutex);
cont++;
printf("%d\n", cont);
if(cont == 10)
{
printf("signal:\n");
pthread_cond_signal(&cond);
// sleep(1);
}
pthread_mutex_unlock(&myMutex);
}
printf("Done func\n");
pthread_exit(NULL);
}
void *anotherFunc(void*)
{
printf("anotherFunc\n");
pthread_mutex_lock(&myMutex);
printf("waiting...\n");
pthread_cond_wait(&cond, &myMutex);
cont += 10;
printf("slot\n");
pthread_mutex_unlock(&myMutex);
printf("mutex unlocked anotherFunc\n");
printf("Done anotherFunc\n");
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
pthread_t thread;
pthread_t anotherThread;
pthread_attr_init(&attr);
pthread_mutex_init(&myMutex, NULL);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_cond_init(&cond, NULL);
pthread_create(&anotherThread, &attr, anotherFunc, NULL);
pthread_create(&thread, &attr, func, NULL);
pthread_join(thread, NULL);
pthread_join(anotherThread, NULL);
printf("Done MAIN()");
pthread_mutex_destroy(&myMutex);
pthread_cond_destroy(&cond);
pthread_attr_destroy(&attr);
pthread_exit(NULL);
return 0;
}
Sorry for the long post but I’m new to threads and I’m willing to learn. Also do you know some good references or courses/tutorials on threads and networking on Linux? I want to learn create an chat client and I heard that I have to know threads and networking for that. Problem is I don’t know pretty good if what I learn is ok since I don’t know what I have to know.
Thank you so much 🙂
Your
anotherThreadsimply callspthread_cond_waitwithout first testing whether the desired condition (counter reaching ten) has already happened. This is incorrect logic, which will lead to the lost wakeup problem: the name of a recurring bug that plagues incorrectly written multithreaded programs.Condition variables are stateless. If
pthread_cond_signalorpthread_cond_broadcastis called on a condition on which no threads are currently waiting, the operation has no effect. It is not remembered. So it is possible for your signaling thread to count to10very quickly, and signal the condition variable, before the other thread has reached thepthread_cond_waitcall.You need a loop around
pthread_cond_wait. The condition must be checked in case it is already true, so that the thread does not wait for a wakeup which already happened. And it should be a loop because wakeups can be spurious: just because the thread falls through thepthread_cond_waitdoesn’t mean that the condition is actually true:Also, there is no need to create a thread attribute just to make a thread joinable. This is the default situation when you use a null pointer for the creation attribute. POSIX threads are joinable unless created detached, or converted to detached with
pthread_detach.Another thing: whenever possible, avoid calling
pthread_cond_signalwhile holding a mutex lock. It’s not incorrect, but it’s potentially wasteful, because the operation may actually have to call into the OS kernel to wake up a thread, and so you’re holding this expensive mutex lock over the entire system call (when all you really need it for is protecting a few machine instructions that working with shared data in your application).