I am writing a program to test my understanding of condition variables. Basically, thread 0 checks if count is even, and if so, increments it. If not, then it signals thread 1 which increments the count variable. The process continues until count reaches 15. Here is my code:
#include <pthread.h>
#include <stdio.h>
#define numThreads 2
int count=0;
pthread_mutex_t count_mutex;
pthread_cond_t count_threshold_cv;
void *checkEven(void *threadId)
{ while(count<=15){
//lock the mutex
pthread_mutex_lock(&count_mutex);
printf("even_thread: thread_id=%d count=%d\n",threadId,count);
if(count%2==0){
count++;
}
else{
printf("Odd count found, signalling to odd thread\n");
pthread_cond_signal(&count_threshold_cv);
}
pthread_mutex_unlock(&count_mutex);
sleep(1);
}
}
void *checkOdd(void *threadId)
{
pthread_mutex_lock(&count_mutex); //obtain a lock
while(count<=15){
pthread_cond_wait(&count_threshold_cv, &count_mutex); //wait() relinquishes the lock
count++;
printf("odd_thread: thread_id=%d, count=%d\n",threadId,count);
}
pthread_mutex_unlock(&count_mutex);
pthread_exit(NULL);
}
int main()
{
pthread_t threads[numThreads];
int rc;
int a=0;
int b=0;
pthread_create(&threads[0], NULL, checkEven, (void *)a);
pthread_create(&threads[1], NULL, checkEven, (void *)b);
pthread_join(0,NULL);
pthread_join(1,NULL);
pthread_exit(NULL);
}
Can someone tell me why I am getting segmentation fault(core dumped) error with this? I know that this error occurs when one process tries to violate the address space of some other process, but nothing beyond this.Can someone please help? Thanks!
You're passing a zero to pthread_join as the thread you want to join:
pthread_join(0,NULL);
You wanted:
pthread_join(threads[0],NULL);
pthread_join(threads[1],NULL);
You have several other bugs though. For one thing, your checkOdd code calls pthread_cond_wait even when it's that thread's turn.
You don't seem to understand condition variables. Specifically, you seem to think that somehow the condition variable will know whether or not the thing you are waiting for has happened. It does not -- condition variables are stateless. It's your job to keep track of what you're waiting for and whether or not it has happened.
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 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
Firstly, I'm Italian and sorry for my bad English.
Anyway, I should do this exercise:
"Write in C a programm which generate a thread. The main shows odd number from 1 to 9, the thread shows even number from 2 to 10. Synchronize the main and the thread with semaphores"
I have written the pseudocode in this way:
//semaphores
semParent = free
semChild = busy
main
generate thread "child"
for i=1 to 9 step 2
P(semParent)
print i
V(semChild)
end for
end main
child
for i=2 to 10 step 2
P(semChild)
print i
V(semParent)
end child
And this is how I have implemented in C:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t semParent;
pthread_mutex_t semChild = PTHREAD_MUTEX_INITIALIZER;
void* functionChild (void* arg) {
for(int i=2; i<=10; i+=2) {
pthread_mutex_lock(&semChild);
printf("CHILD: %d\n",i);
pthread_mutex_unlock(&semParent);
}
return NULL;
}
int main(void) {
pthread_t child;
pthread_create(&child, NULL, &functionChild, NULL);
pthread_mutex_init(&semParent, NULL);
for(int i=1; i<=9; i+=2) {
pthread_mutex_lock(&semParent);
printf("PARENT : %d\n",i);
pthread_mutex_unlock(&semChild);
}
pthread_join(child, NULL);
}
But the output is always different whenever I run the program.
What's wrong?
I use CygWin64 Terminal in Windows 10 64 bit.
Thanks in advance.
A pthread_mutex_t is not a semaphore (though a semaphore can be used as a mutex if you do a "V" to initialize it to "free"). The semaphore API is sem_init, sem_post and sem_wait.
By using pthread_mutex_unlock on a mutex that was locked by another thread, your program is triggering undefined behavior.
This may not be the cause of the problem you are experiencing now, but you should never use printf() in a multithreaded program. printf() writes to a buffer and doesn't always print to the screen right away. Instead you should use sprintf() and write:
char buff[20];
sprintf("PARENT: %d\n", i);
write(1, buff, strlen(buff));
I think that pthread_mutex_init(&semParent, NULL) with NULL attributes and PTHREAD_MUTEX_INITIALIZER have the same effect, which is both locks are initialised to unlocked. Your problem though does not have a critical section with the strict meaning. So a better solution whould be condition variables as #Serhio mentioned. You can also check out semaphores http://www.csc.villanova.edu/~mdamian/threads/posixsem.html which give bigger freedom and can also have the functionality of mutexes.
Below program gives me segmentation fault(core dumped) error on random instances. sometimes it runs without any error. The program is just for understanding deadlocks.
Even though I have run this program for about 15 times, I haven't faced a deadlock so far. Sometimes the program runs smoothly(which can be expected) and sometimes it gives the segmentation fault(which is not expected). Why do I get the segmentation fault?
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
int a=5;
int b=3;
pthread_mutex_t mutex1,mutex2;
void* add_subtract(){
pthread_mutex_lock(&mutex1);
pthread_mutex_lock(&mutex2);
a=a+2;
b=b-2;
printf("%d %d\n",a,b);
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
}
void* subtract_add(){
pthread_mutex_lock(&mutex2);
pthread_mutex_lock(&mutex1);
b=b-2;
a=a+2;
printf("%d %d\n",a,b);
pthread_mutex_unlock(&mutex1);
pthread_mutex_unlock(&mutex2);
}
int main(){
pthread_t thread1,thread2;
pthread_create(&thread1,NULL,add_subtract(),NULL);
pthread_create(&thread2,NULL,subtract_add(),NULL);
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
return 0;
}
When you pass add_subtract() as an argument, you're calling the function and then passing the return value as the argument. In this case you want to pass the function itself... try it without the parens.
I think you need to initialize the mutex: http://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_mutex_init.html
The pthread_mutex_init() function initialises the mutex referenced by
mutex with attributes specified by attr. If attr is NULL, the default
mutex attributes are used; the effect is the same as passing the
address of a default mutex attributes object. Upon successful
initialisation, the state of the mutex becomes initialised and
unlocked.