#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_t node[4];
pthread_mutex_t token;
pthread_cond_t cond;
int id=0;
void *func(int n)
{
int count = 0;
while (count < 10){
pthread_mutex_lock(&token);
while (id != n){
printf("Whoops not my turn, id=%d\n",n);
pthread_cond_wait(&cond, &token);}
//if (id == n){
count += 1;
printf ("My turn! id= %d\n",n);
printf("count %d\n", count);
if (id == 3){
id = 0;}
else{
id += 1;}
//}else{
// printf("Not my turn! id=%d\n",n);}
// pthread_mutex_unlock(&token);
// sleep(2);}
pthread_mutex_unlock(&token);
pthread_cond_signal(&cond);}
printf ("ID=%d has finished\n",n);
return(NULL);
}
int main()
{
int i;
pthread_mutex_init(&token,NULL);
pthread_cond_init(&cond,NULL);
for(i=0;i<4;i++)
pthread_create(&node[i],NULL,(void *)func,(void *)i);
for(i=0;i<4;i++)
pthread_join(node[i],NULL);
pthread_mutex_destroy(&token);
return 0;
}
This is my code, it is a C program using threads. I don't think it's purpose needs to be known here, but I will give an example of the problem I have.
Say thread with id 1 (defined by n in func) gets the mutex, and returns "My turn! id=1". When mutex_unlock and cond_signal are called, the next thread to get the mutex will actually be thread with id 1 again, and it will print "Whoops not my turn, id=1". And only then will thread with id 2 get the mutex, and print "My turn! id=2", but when thread with id = 2 will get the mutex after that. Here is my program output:
Whoops not my turn, id=1
Whoops not my turn, id=2
Whoops not my turn, id=3
My turn! id= 0
count 1
Whoops not my turn, id=0
My turn! id= 1
count 1
Whoops not my turn, id=1
My turn! id= 2
count 1
Whoops not my turn, id=2
My turn! id= 3
count 1
Whoops not my turn, id=3
My turn! id= 0
count 2
Whoops not my turn, id=0
My turn! id= 1
count 2
Whoops not my turn, id=1
My turn! id= 2
count 2
Whoops not my turn, id=2
My turn! id= 3
count 2
Whoops not my turn, id=3
My turn! id= 0
count 3
Whoops not my turn, id=0
My turn! id= 1
count 3
Whoops not my turn, id=1
My turn! id= 2
count 3
Whoops not my turn, id=2
My turn! id= 3
count 3
Whoops not my turn, id=3
My turn! id= 0
count 4
Whoops not my turn, id=0
My turn! id= 1
count 4
Whoops not my turn, id=1
My turn! id= 2
count 4
Whoops not my turn, id=2
My turn! id= 3
count 4
Whoops not my turn, id=3
My turn! id= 0
count 5
Whoops not my turn, id=0
My turn! id= 1
count 5
Whoops not my turn, id=1
My turn! id= 2
count 5
Whoops not my turn, id=2
My turn! id= 3
count 5
Whoops not my turn, id=3
My turn! id= 0
count 6
Whoops not my turn, id=0
My turn! id= 1
count 6
Whoops not my turn, id=1
My turn! id= 2
count 6
Whoops not my turn, id=2
My turn! id= 3
count 6
Whoops not my turn, id=3
My turn! id= 0
count 7
Whoops not my turn, id=0
My turn! id= 1
count 7
Whoops not my turn, id=1
My turn! id= 2
count 7
Whoops not my turn, id=2
My turn! id= 3
count 7
Whoops not my turn, id=3
My turn! id= 0
count 8
Whoops not my turn, id=0
My turn! id= 1
count 8
Whoops not my turn, id=1
My turn! id= 2
count 8
Whoops not my turn, id=2
My turn! id= 3
count 8
Whoops not my turn, id=3
My turn! id= 0
count 9
Whoops not my turn, id=0
My turn! id= 1
count 9
Whoops not my turn, id=1
My turn! id= 2
count 9
Whoops not my turn, id=2
My turn! id= 3
count 9
Whoops not my turn, id=3
My turn! id= 0
count 10
ID=0 has finished
My turn! id= 1
count 10
ID=1 has finished
My turn! id= 2
count 10
ID=2 has finished
My turn! id= 3
count 10
ID=3 has finished
As you can see, after each success, and the thread prints "My turn!", it will get the mutex after that and cause an "Whoops not my turn!". I don't understand why this happens as I call pthread_cond_signal, which should signal another thread to wake up before the current thread can reobtain the mutex. Please help me find this solution as I think there is something important I am missing. If my explanation is lacking, please feel free to ask me for more information. Thank you very much for your time!
@rcgldr already gave a very good explanation on the timing involved. If you want to increase your odds of giving another thread a chance, try adding a call to pthread_yield, which should give the scheduler the opportunity to pick a different thread, though that won't be a guarantee, either.