I'm new at threading I want to use ptherad_cond_signal & pthread_cond_wait to check some condition I have this code as a sample:
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int x = 0;
void* f1(void *arg){
for (int i = 0; i < 10; i )
{
pthread_mutex_lock(&lock);
x = 10;
printf("%d\n", x);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
return NULL;
}
void* f2(void* arg){
pthread_mutex_lock(&lock);
while (x < 40)
{
pthread_cond_wait(&cond, &lock);
}
x -= 40;
pthread_mutex_unlock(&lock);
return NULL;
}
int main(int argc, char *args[]){
pthread_t p1, p2;
pthread_create(&p2, NULL, f2, NULL);
pthread_create(&p1, NULL, f1, NULL);
pthread_exit(NULL);
return 0;
}
result:
10
20
30
40
50
60
70
80
90
100
but I expect:
10
20
30
40
10
20
30
40
50
60
why after pthread_cond_signal, function f2 doesn't continue?
It seems in f1 for loop, locks again before pthread_cond_wait wakeing up
CodePudding user response:
Your first issue is that main
creates two threads, but will likely exit (and exit your program) before the other two threads complete. Maybe there's a nuance of threads on a Linux build waits for all threads to complete before exiting a process when main returns. I always forget the rules here, but this is my preferred pattern for main
to wait for the child threads to complete. It's a simple change
int main(int argc, char *args[]){
pthread_t p1, p2;
pthread_create(&p2, NULL, f2, NULL);
pthread_create(&p1, NULL, f1, NULL);
// wait for both threads to complete
pthread_join(&p1, NULL);
pthread_join(&p2, NULL);
return 0;
}
Back to your original issue.
There's nothing that blocks f1
from incrementing to 100 before a context switch to f2
.
It sounds like what you want is for f1
to increment X to 40, then wait for f2
to drop it back down before continuing the increment interval up to 60 again.
You can easily use your condition variable in both threads to be notified of changes and to wait on the other thread.
I've refactored some of your code so I didn't have to re-write the same block over and over. But it's still mostly your original code.
void IncrementX(int val)
{
pthread_mutex_lock(&lock);
x = 10;
printf("%d\n", x);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
void WaitForX(int target, int gt)
{
pthread_mutex_lock(&lock);
while ((x >= target && gt) || (x < target && !gt))
{
pthread_cond_wait(&cond, &lock);
}
pthread_mutex_unlock(&lock);
}
void* f1(void *arg){
// increment to 40
for (int i = 0; i < 4; i )
{
IncrementX(10);
}
WaitForX(40, 0); // wait for X to drop below 40
// increment back to 60
for (int i = 0; i < 6; i )
{
IncrementX(10);
}
return NULL;
}
void* f2(void* arg){
WaitForX(40, 1); // wait for X to go to 40 or above
IncrementX(-40);
return NULL;
}