I using pthread_cond_wait() and pthread_cond_signal() function to create a multithreaded program. It working correctly if condition correct, but condition incorrect, it not working, it not ignore function printinput(), it stay here, not run continue. Can you help me checking this error?
My code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t mutex;
pthread_cond_t cond;
//Read input value
void* readinput(void *arg)
{
pthread_mutex_lock(&mutex);
int a;
printf("Input:");
scanf("%d",&a);
printf("Value: %d\n",a);
/*
if condition correct then "printinput" function
else ignore that function
*/
if (a>=2 && a<=8)
{
pthread_cond_signal(&cond);
}
pthread_mutex_unlock(&mutex);
pthread_exit((void *)a);
}
//print input value if condition correctly
void* printinput(void *arg)
{
pthread_mutex_lock(&mutex);
//Block and wait for cond Singal
pthread_cond_wait(&cond,&mutex);
printf("Your value between 2 and 8 \n\n");
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
int main()
{
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
pthread_t th1;
pthread_t th2;
while (1)
{
//Create pthread
pthread_create(&th1,NULL,&printinput,NULL);
pthread_create(&th2,NULL,&readinput,NULL);
//Wait pthread done
pthread_join(th1,NULL);
pthread_join(th2,NULL);
Sleep(1000);
}
}
Result:
Input:5
Value: 5
Your value between 2 and 8
Input:10 Value: 10
pthread_cond_wait() suspends the current thread until the relevant condition is signalled.
For input 5 the first thread signals the condition as it's part of if (a >= 2 && a <= 8) block.
For input 10 the above block is skipped so the condition is never signalled. Therefore the second thread is never woken up and is stuck forever.
Additionally, note there is race condition and I'm actually surprised that the program is often working. In case the first thread locks the mutex, the second thread doesn't enter the mutex section until the first thread function is finished, therefore the condition is signalled before the wait on that condition is invoked. In such situation the second thread would be stuck forever as well.
For the solution working in the way you expect (i.e. consuming true/false from the first thread in the second thread), I'd suggest implementing a queue into which the first thread sends the outputs and the second thread consumes it. It'll fix the race condition too. For the implementation see for example https://stackoverflow.com/a/4577987/4787126
Related
I am new to pthreads. I am trying to print even and odd numbers from two threads. What is wrong with below code? Its intention is to create two threads - one will print odd numbers and other will print even numbers. The numbers have to be printed in order. It seems to get stuck (time limit exceeded in ideone).. I have spent a lot of time staring at it. Just can't figure out what is wrong..
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t lock;
int n = 0;
int max = 10;
pthread_cond_t even;
pthread_cond_t odd;
void* print_odd(void *x)
{
while(1)
{
pthread_mutex_lock(&lock);
while(n%2 != 0)
{
pthread_cond_wait(&even, &lock);
}
if(n >= max)
{
pthread_mutex_unlock(&lock);
pthread_exit(NULL);
}
printf("Thread A : %d", ++n);
pthread_cond_signal(&odd);
pthread_mutex_unlock(&lock);
}
}
void* print_even(void *x)
{
while(1)
{
pthread_mutex_lock(&lock);
while(n%2 == 0)
{
pthread_cond_wait(&odd, &lock);
}
if(n >= max)
{
pthread_mutex_unlock(&lock);
pthread_exit(NULL);
}
printf("Thread B : %d", ++n);
pthread_cond_signal(&even);
pthread_mutex_unlock(&lock);
}
}
main()
{
pthread_t t1, t2;
pthread_create(&t1, NULL, print_odd, NULL);
pthread_create(&t2, NULL, print_even, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
exit(0);
}
There are multiple issues with your program-
As suggested in the comments, the lock and the conditional variables need to be initialized.
pthread_mutex_t lock = PTHREAD_LOCK_INITIALIZER;
pthread_cond_t even = PTHREAD_COND_INITIALIZER;
pthread_cond_t odd = PTHREAD_COND_INITIALIZER;
You might get lucky accidentally here even without initialization since you've declared them as global and they will be zero-inited and pthread implementations might actually be zero-initing when you properly initialize them.
Your printf doesn't have \n and hence output is not flushed to screen. Just add the newline and you'll see your threads are indeed running.
When n reaches 10, ie when print_odd threads increments from 9, it simply exits without signaling the even thread. Hence your even thread is hung in the cond_wait and your main thread is hung in pthread_join. You can fix this by waking up the even thread by signalling it before exiting the odd thread.
EDIT I found one more issue
Even if the odd thread signals the even thread just before exiting, since n=10, the even thread does NOT exit the while(n%2 == 0) loop and goes back to sleep again. This time, there's no one to wake up the poor soul. It is for this reason that you need to test the termination condition n>=max inside the while loop
pthread_cond_wait is blocking the calling threads. In your case, you have asked the threads to wait on the true conditions of odd and even. Instead, they should wait on the incorrect conditions.
While i%2 == 0, the odd thread should call the wait function inside of the routine.
While i!=2, the even thread should call wait function.
I'm trying to update a global variable in the main function and have a thread tell me when this variable is positive.
The code: https://pastebin.com/r4DUHaUV
When I run it, only 2 shows up though 1 and 2 should be the correct answer.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_t tid;
pthread_mutex_t mtx;
pthread_cond_t cond;
int nr=0;
void* function(void* arg)
{
pthread_mutex_lock(&mtx);
printf("Number in thread : %d \n",nr);
while(nr<=0)
pthread_cond_wait(&cond,&mtx);
printf("Number %d is positive \n",nr);
pthread_mutex_unlock(&mtx);
}
int main()
{
pthread_mutex_init(&mtx,NULL);
pthread_create(&tid,NULL,function,NULL);
int i;
for(i=0;i<3;i++)
{
int isPos=0;
pthread_mutex_lock(&mtx);
if(i==0)
nr=nr+1;
if(i==1)
nr=nr-2;
if(i==2)
nr=nr+3;
if(nr>0)
isPos=1;
if(isPos==1)
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mtx);
}
pthread_join(tid,NULL);
return 0;
}
As I mentioned in general comment, I'll repeat here:
There is no guarantee the main thread won't go off, locking the mutex,
changing nr, signaling the cv (whether or not anyone is actually
waiting on it), and unlocking the mutex, all before the child thread
even locks the mutex, much less starts waiting on the cv. In that
case, nr can be 1 (or 2, etc) when the child finally gets the mutex.
That means your while loop will be skipped (nr<=0 is not true), and
whatever the current value of nr is will be printed on the way out.
I've run this several times, and gotten 1x1, 1x2, and 2x2, multiple
times.
A simple fix for this involves using the cv/mtx pair you've set up for monitoring for changes from main to also monitor startup-start from function. First the code:
The Code
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int nr = -1;
void* function(void* arg)
{
// signal main to start up once we start waiting
pthread_mutex_lock(&mtx);
nr = 0;
pthread_cond_signal(&cond);
// now start waiting (which will unlock the mutex as well, which means
// the main thread will be be able to acquire it and check nr safely
while(nr<=0)
pthread_cond_wait(&cond,&mtx);
printf("Number %d is positive \n",nr);
pthread_mutex_unlock(&mtx);
return NULL;
}
int main()
{
pthread_t tid;
pthread_create(&tid,NULL,function,NULL);
// wait until child is knowingly waiting
pthread_mutex_lock(&mtx);
while (nr != 0)
pthread_cond_wait(&cond, &mtx);
pthread_mutex_unlock(&mtx);
// now we know the child is ready to receive signals
int i;
for(i=0;i<3;i++)
{
pthread_mutex_lock(&mtx);
if(i==0)
nr=nr+1;
if(i==1)
nr=nr-2;
if(i==2)
nr=nr+3;
int isPos = (nr>0);
pthread_mutex_unlock(&mtx);
if (isPos)
pthread_cond_signal(&cond);
}
pthread_join(tid,NULL);
return 0;
}
How It Works
The initial value of nr is established as -1. Only the child thread will change this directly to 0, and even then only under the protection of the predicate mutex.
// signal main to start up once we start waiting
pthread_mutex_lock(&mtx);
nr = 0;
pthread_cond_signal(&cond);
Note that after the above three lines, the child still owns the mutex. It atomically releases it and begins waiting for notifications with the first entry into the subsequent loop:
while(nr<=0)
pthread_cond_wait(&cond,&mtx);
Now, back in main, the startup creates the child thread, acquires the mutex, then monitors until nr is zero.
pthread_create(&tid,NULL,function,NULL);
// wait until child is knowingly waiting
pthread_mutex_lock(&mtx);
while (nr != 0)
pthread_cond_wait(&cond, &mtx);
pthread_mutex_unlock(&mtx);
The only way to make it past this is when nr == 0. When that happens, the child must have changed it, but more importantly, it also must be waiting on the condition variable (that is how we got the mutex; remember?) From that point on, the code is similar. Worth noting, I use the pthread initializers to ensure the mutex and cvar are properly stood up. Your original post was missing the cvar initialization.
Lastly, doing multiple-predicate double-duty with a single cvar-mtx pair is easy to mess up, and can be very hard to detect edge cases when you did (mess up, that is). Be careful. This specific example is a hand-off sequence of duties, not concurrent duties, making it fairly trivial, so I'm comfortable in showing it.
Hope it helps.
I am trying to learn how to use conditional variables properly in C.
As an exercise for myself I am trying to make a small program with 2 threads that print "Ping" followed by "Pong" in an endless loop.
I have written a small program:
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void* T1(){
printf("thread 1 started\n");
while(1)
{
pthread_mutex_lock(&lock);
sleep(0.5);
printf("ping\n");
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
pthread_cond_wait(&cond,&lock);
}
}
void* T2(){
printf("thread 2 started\n");
while(1)
{
pthread_cond_wait(&cond,&lock);
pthread_mutex_lock(&lock);
sleep(0.5);
printf("pong\n");
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
}
int main(void)
{
int i = 1;
pthread_t t1;
pthread_t t2;
printf("main\n");
pthread_create(&t1,NULL,&T1,NULL);
pthread_create(&t2,NULL,&T2,NULL);
while(1){
sleep(1);
i++;
}
return EXIT_SUCCESS;
}
And when running this program the output I get is:
main
thread 1 started
thread 2 started
ping
Any idea what is the reason the program does not execute as expected?
Thanks in advance.
sleep takes an integer, not a floating point. Not sure what sleep(0) does on your system, but it might be one of your problems.
You need to hold the mutex while calling pthread_cond_wait.
Naked condition variables (that is condition variables that don't indicate that there is a condition to read somewhere else) are almost always wrong. A condition variable indicates that something we are waiting for might be ready to be consumed, they are not for signalling (not because it's illegal, but because it's pretty hard to get them right for pure signalling). So in general a condition will look like this:
/* consumer here */
pthread_mutex_lock(&something_mutex);
while (something == 0) {
pthread_cond_wait(&something_cond, &something_mutex);
}
consume(something);
pthread_mutex_unlock(&something_mutex);
/* ... */
/* producer here. */
pthread_mutex_lock(&something_mutex);
something = 4711;
pthread_cond_signal(&something_cond, &something_mutex);
pthread_mutex_unlock(&something_mutex);
It's a bad idea to sleep while holding locks.
T1 and T2 are not valid functions to use as functions to pthread_create they are supposed to take arguments. Do it right.
You are racing yourself in each thread between cond_signal and cond_wait, so it's not implausible that each thread might just signal itself all the time. (correctly holding the mutex in the calls to pthread_cond_wait may help here, or it may not, that's why I said that getting naked condition variables right is hard, because it is).
First of all you should never use sleep() to synchronize threads (use nanosleep() if you need to reduce output speed). You may need (it's a common use) a shared variable ready to let each thread know that he can print the message. Before you make a pthread_cond_wait() you must acquire the lock because the pthread_cond_wait() function shall block on a condition variable. It shall be called with mutex locked by the calling thread or undefined behavior results.
Steps are:
Acquire the lock
Use wait in a while with a shared variable in guard[*]
Do stuffs
Change the value of shared variable for synchronize (if you've one) and signal/broadcast that you finished to work
Release the lock
Steps 4 and 5 can be reversed.
[*]You use pthread_cond_wait() to release the mutex and block the thread on the condition variable and when using condition variables there is always a Boolean predicate involving shared variables associated with each condition wait that is true if the thread should proceed because spurious wakeups may occur. watch more here
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int ready = 0;
void* T1(){
printf("thread 1 started\n");
while(1)
{
pthread_mutex_lock(&lock);
while(ready == 1){
pthread_cond_wait(&cond,&lock);
}
printf("ping\n");
ready = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
}
void* T2(){
printf("thread 2 started\n");
while(1)
{
pthread_mutex_lock(&lock);
while(ready == 0){
pthread_cond_wait(&cond,&lock);
}
printf("pong\n");
ready = 0;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
}
int main(void)
{
int i = 1;
pthread_t t1;
pthread_t t2;
printf("main\n");
pthread_create(&t1,NULL,&T1,NULL);
pthread_create(&t2,NULL,&T2,NULL);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
return EXIT_SUCCESS;
}
You should also use pthread_join() in main instead of a while(1)
I am trying to write a code that does not block main() when pthread_join() is called:
i.e. basically trying to implement my previous question mentioned below:
https://stackoverflow.com/questions/24509500/pthread-join-and-main-blocking-multithreading
And the corresponding explanation at:
pthreads - Join on group of threads, wait for one to exit
As per suggested answer:
You'd need to create your own version of it - e.g. an array of flags (one flag per thread) protected by a mutex and a condition variable; where just before "pthread_exit()" each thread acquires the mutex, sets its flag, then does "pthread_cond_signal()". The main thread waits for the signal, then checks the array of flags to determine which thread/s to join (there may be more than one thread to join by then).
I have tried as below:
My status array which keeps a track of which threads have finished:
typedef struct {
int Finish_Status[THREAD_NUM];
int signalled;
pthread_mutex_t mutex;
pthread_cond_t FINISHED;
}THREAD_FINISH_STATE;
The thread routine, it sets the corresponding array element when the thread finishes and also signals the condition variable:
void* THREAD_ROUTINE(void* arg)
{
THREAD_ARGUMENT* temp=(THREAD_ARGUMENT*) arg;
printf("Thread created with id %d\n",temp->id);
waitFor(5);
pthread_mutex_lock(&(ThreadFinishStatus.mutex));
ThreadFinishStatus.Finish_Status[temp->id]=TRUE;
ThreadFinishStatus.signalled=TRUE;
if(ThreadFinishStatus.signalled==TRUE)
{
pthread_cond_signal(&(ThreadFinishStatus.FINISHED));
printf("Signal that thread %d finished\n",temp->id);
}
pthread_mutex_unlock(&(ThreadFinishStatus.mutex));
pthread_exit((void*)(temp->id));
}
I am not able to write the corresponding parts pthread_join() and pthread_cond_wait() functions. There are a few things which I am not able to implement.
1) How to write corresponding part pthread_cond_wait() in my main()?
2) I am trying to write it as:
pthread_mutex_lock(&(ThreadFinishStatus.mutex));
while((ThreadFinishStatus.signalled != TRUE){
pthread_cond_wait(&(ThreadFinishStatus.FINISHED), &(ThreadFinishStatus.mutex));
printf("Main Thread signalled\n");
ThreadFinishStatus.signalled==FALSE; //Reset signalled
//check which thread to join
}
pthread_mutex_unlock(&(ThreadFinishStatus.mutex));
But it does not enter the while loop.
3) How to use pthread_join() so that I can get the return value stored in my arg[i].returnStatus
i.e. where to put below statement in my main:
`pthread_join(T[i],&(arg[i].returnStatus));`
COMPLETE CODE
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#define THREAD_NUM 5
#define FALSE 0
#define TRUE 1
void waitFor (unsigned int secs) {
time_t retTime;
retTime = time(0) + secs; // Get finishing time.
while (time(0) < retTime); // Loop until it arrives.
}
typedef struct {
int Finish_Status[THREAD_NUM];
int signalled;
pthread_mutex_t mutex;
pthread_cond_t FINISHED;
}THREAD_FINISH_STATE;
typedef struct {
int id;
void* returnStatus;
}THREAD_ARGUMENT;
THREAD_FINISH_STATE ThreadFinishStatus;
void initializeState(THREAD_FINISH_STATE* state)
{
int i=0;
state->signalled=FALSE;
for(i=0;i<THREAD_NUM;i++)
{
state->Finish_Status[i]=FALSE;
}
pthread_mutex_init(&(state->mutex),NULL);
pthread_cond_init(&(state->FINISHED),NULL);
}
void destroyState(THREAD_FINISH_STATE* state)
{
int i=0;
for(i=0;i<THREAD_NUM;i++)
{
state->Finish_Status[i]=FALSE;
}
pthread_mutex_destroy(&(state->mutex));
pthread_cond_destroy(&(state->FINISHED));
}
void* THREAD_ROUTINE(void* arg)
{
THREAD_ARGUMENT* temp=(THREAD_ARGUMENT*) arg;
printf("Thread created with id %d\n",temp->id);
waitFor(5);
pthread_mutex_lock(&(ThreadFinishStatus.mutex));
ThreadFinishStatus.Finish_Status[temp->id]=TRUE;
ThreadFinishStatus.signalled=TRUE;
if(ThreadFinishStatus.signalled==TRUE)
{
pthread_cond_signal(&(ThreadFinishStatus.FINISHED));
printf("Signal that thread %d finished\n",temp->id);
}
pthread_mutex_unlock(&(ThreadFinishStatus.mutex));
pthread_exit((void*)(temp->id));
}
int main()
{
THREAD_ARGUMENT arg[THREAD_NUM];
pthread_t T[THREAD_NUM];
int i=0;
initializeState(&ThreadFinishStatus);
for(i=0;i<THREAD_NUM;i++)
{
arg[i].id=i;
}
for(i=0;i<THREAD_NUM;i++)
{
pthread_create(&T[i],NULL,THREAD_ROUTINE,(void*)&arg[i]);
}
/*
Join only if signal received
*/
pthread_mutex_lock(&(ThreadFinishStatus.mutex));
//Wait
while((ThreadFinishStatus.signalled != TRUE){
pthread_cond_wait(&(ThreadFinishStatus.FINISHED), &(ThreadFinishStatus.mutex));
printf("Main Thread signalled\n");
ThreadFinishStatus.signalled==FALSE; //Reset signalled
//check which thread to join
}
pthread_mutex_unlock(&(ThreadFinishStatus.mutex));
destroyState(&ThreadFinishStatus);
return 0;
}
Here is an example of a program that uses a counting semaphore to watch as threads finish, find out which thread it was, and review some result data from that thread. This program is efficient with locks - waiters are not spuriously woken up (notice how the threads only post to the semaphore after they've released the mutex protecting shared state).
This design allows the main program to process the result from some thread's computation immediately after the thread completes, and does not require the main wait for all threads to complete. This would be especially helpful if the running time of each thread varied by a significant amount.
Most importantly, this program does not deadlock nor race.
#include <pthread.h>
#include <semaphore.h>
#include <stdlib.h>
#include <stdio.h>
#include <queue>
void* ThreadEntry(void* args );
typedef struct {
int threadId;
pthread_t thread;
int threadResult;
} ThreadState;
sem_t completionSema;
pthread_mutex_t resultMutex;
std::queue<int> threadCompletions;
ThreadState* threadInfos;
int main() {
int numThreads = 10;
int* threadResults;
void* threadResult;
int doneThreadId;
sem_init( &completionSema, 0, 0 );
pthread_mutex_init( &resultMutex, 0 );
threadInfos = new ThreadState[numThreads];
for ( int i = 0; i < numThreads; i++ ) {
threadInfos[i].threadId = i;
pthread_create( &threadInfos[i].thread, NULL, &ThreadEntry, &threadInfos[i].threadId );
}
for ( int i = 0; i < numThreads; i++ ) {
// Wait for any one thread to complete; ie, wait for someone
// to queue to the threadCompletions queue.
sem_wait( &completionSema );
// Find out what was queued; queue is accessed from multiple threads,
// so protect with a vanilla mutex.
pthread_mutex_lock(&resultMutex);
doneThreadId = threadCompletions.front();
threadCompletions.pop();
pthread_mutex_unlock(&resultMutex);
// Announce which thread ID we saw finish
printf(
"Main saw TID %d finish\n\tThe thread's result was %d\n",
doneThreadId,
threadInfos[doneThreadId].threadResult
);
// pthread_join to clean up the thread.
pthread_join( threadInfos[doneThreadId].thread, &threadResult );
}
delete threadInfos;
pthread_mutex_destroy( &resultMutex );
sem_destroy( &completionSema );
}
void* ThreadEntry(void* args ) {
int threadId = *((int*)args);
printf("hello from thread %d\n", threadId );
// This can safely be accessed since each thread has its own space
// and array derefs are thread safe.
threadInfos[threadId].threadResult = rand() % 1000;
pthread_mutex_lock( &resultMutex );
threadCompletions.push( threadId );
pthread_mutex_unlock( &resultMutex );
sem_post( &completionSema );
return 0;
}
Pthread conditions don't have "memory"; pthread_cond_wait doesn't return if pthread_cond_signal is called before pthread_cond_wait, which is why it's important to check the predicate before calling pthread_cond_wait, and not call it if it's true. But that means the action, in this case "check which thread to join" should only depend on the predicate, not on whether pthread_cond_wait is called.
Also, you might want to make the while loop actually wait for all the threads to terminate, which you aren't doing now.
(Also, I think the other answer about "signalled==FALSE" being harmless is wrong, it's not harmless, because there's a pthread_cond_wait, and when that returns, signalled would have changed to true.)
So if I wanted to write a program that waited for all threads to terminate this way, it would look more like
pthread_mutex_lock(&(ThreadFinishStatus.mutex));
// AllThreadsFinished would check that all of Finish_Status[] is true
// or something, or simpler, count the number of joins completed
while (!AllThreadsFinished()) {
// Wait, keeping in mind that the condition might already have been
// signalled, in which case it's too late to call pthread_cond_wait,
// but also keeping in mind that pthread_cond_wait can return spuriously,
// thus using a while loop
while (!ThreadFinishStatus.signalled) {
pthread_cond_wait(&(ThreadFinishStatus.FINISHED), &(ThreadFinishStatus.mutex));
}
printf("Main Thread signalled\n");
ThreadFinishStatus.signalled=FALSE; //Reset signalled
//check which thread to join
}
pthread_mutex_unlock(&(ThreadFinishStatus.mutex));
Your code is racy.
Suppose you start a thread and it finishes before you grab the mutex in main(). Your while loop will never run because signalled was already set to TRUE by the exiting thread.
I will echo #antiduh's suggestion to use a semaphore that counts the number of dead-but-not-joined threads. You then loop up to the number of threads spawned waiting on the semaphore. I'd point out that the POSIX sem_t is not like a pthread_mutex in that sem_wait can return EINTR.
Your code appears fine. You have one minor buglet:
ThreadFinishStatus.signalled==FALSE; //Reset signalled
This does nothing. It tests whether signalled is FALSE and throws away the result. That's harmless though since there's nothing you need to do. (You never want to set signalled to FALSE because that loses the fact that it was signalled. There is never any reason to unsignal it -- if a thread finished, then it's finished forever.)
Not entering the while loop means signalled is TRUE. That means the thread already set it, in which case there is no need to enter the loop because there's nothing to wait for. So that's fine.
Also:
ThreadFinishStatus.signalled=TRUE;
if(ThreadFinishStatus.signalled==TRUE)
There's no need to test the thing you just set. It's not like the set can fail.
FWIW, I would suggest re-architecting. If the existing functions like pthread_join don't do exactly what you want, just don't use them. If you're going to have structures that track what work is done, then totally separate that from thread termination. Since you will already know what work is done, what different does it make when and how threads terminate? Don't think of this as "I need a special way to know when a thread terminates" and instead think of this "I need to know what work is done so I can do other things".
I have written the following code to get the understanding of event ordering using pthreads and mutex. main function creates two threads which are associated to functions func1 and func2. Function func1 checks for the value of count and conditionally wait for func2 to signal it. Function func2 increments the count and when count reaches 50000, it signals func1.
Then func1 prints the value of count which is(or should be) at that time 50000.
But in actual output, along with 50000 some other values are also being printed. I am not getting any reason why is it so. What I think is, when func2 signals, func1 wakes up and execute from after the pthread_cond_wait statement, and so it should print only 50000. Please point out where I am wrong and what should be changed to get correct output?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
pthread_mutex_t evmutex;
pthread_cond_t evcond;
char a;
int count;
int N = 50000;
void *func1()
{
while(1)
{
pthread_mutex_lock(&evmutex);
if(count < N)
{
pthread_cond_wait(&evcond,&evmutex);
printf("%d\n",count);
count = 0;
}
pthread_mutex_unlock(&evmutex);
}
}
void *func2()
{
while(1)
{
pthread_mutex_lock(&evmutex);
count++;
if(count == N)
{
pthread_cond_signal(&evcond);
}
pthread_mutex_unlock(&evmutex);
}
}
int main ()
{
pthread_t ptd1,ptd2;
pthread_mutex_init(&evmutex,NULL);
pthread_cond_init(&evcond,NULL);
count = 0;
pthread_create(&ptd1,NULL,func1,NULL);
pthread_create(&ptd2,NULL,func2,NULL);
pthread_exit(NULL);
pthread_mutex_destroy(&evmutex);
pthread_cond_destroy(&evcond);
return 0;
}
You've not synchronized with the producer, func2(), and telling it to wait until the consumer, func1(), has processed the condition.
Nothing stops the producer from signalling the condition, re-acquiring the mutex, and incrementing the counter again. pthread_cond_signal doesn't mean your producer will halt and wait for the consumer to process.
This means the producer might increment the counter many times before your consumer gets scheduled and wakes up to print the current number.
You'd need to add another condition variable which the producer waits for after it's incremented the counter to N, and have the consumer signal that when it has processed the counter.
In addition to that, you need to handle spurious wakeups as other answers mentions.
Some implementations of pthread_cond_wait() suffer from spurious wake-ups, and because of this, it's common practice to use a while (cond) { pthread_cond_wait(...); } loop to work around this.
I found a good explanation of the problem and causes here: Why does pthread_cond_wait have spurious wakeups?