Writing simple C code, trying to control output from two different threads:
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
sem_t sem;
void* thread_func(void* aArgs)
{
printf("Entering thread %p with %d\n", (void*)pthread_self(), (int)aArgs);
int i = 0;
for(;i < 10; i++)
{
sem_wait(&sem);
if ((i % 2) == (int)aArgs)
printf("val is %d in thread %p \n", i, (void*)pthread_self());
sem_post(&sem);
}
}
int main()
{
pthread_t thread_1, thread_2;
sem_init(&sem, 0, 1);
pthread_create(&thread_1, NULL, (void*)thread_func, (void*)0);
pthread_create(&thread_2, NULL, (void*)thread_func, (void*)1);
pthread_join(thread_1, NULL);
pthread_join(thread_2, NULL);
sem_destroy(&sem);
return 0;
}
What i want to achieve, is sequence of intermixed odd and even numbers. But i receive all the numbers from one thread then all another numbers from the second thread, like this (even if i increase loop counter magnitude):
Entering thread 0xb75f2b40 with 0
val is 0 in thread 0xb75f2b40
val is 2 in thread 0xb75f2b40
val is 4 in thread 0xb75f2b40
val is 6 in thread 0xb75f2b40
val is 8 in thread 0xb75f2b40
Entering thread 0xb6df1b40 with 1
val is 1 in thread 0xb6df1b40
val is 3 in thread 0xb6df1b40
val is 5 in thread 0xb6df1b40
val is 7 in thread 0xb6df1b40
val is 9 in thread 0xb6df1b40
The question is why two independent threads behave like they were two sequential tasks? Why the second thread didn't take the execution control until the first were not finished all the stuff?
I've tried to add pthread_yield() to the end of the for-loop, but situation doesn't change significantly: sometimes i get expected output, sometimes - as described above.
UPD. How can i achieve deterministic one-by-one thread execution? Is there any synchronisation primitive for this?
If you want to get the desired output, you should use two semaphores instead of one. Each thread should wait on its own semaphore and post the other thread's semaphore after it is done with each loop iteration. The main thread can create one semaphore with a value of 1 and the other with a value of zero to start things off right. This will force the two threads to run in an alternating sequence.
As the program is written currently, doing a sem_post
followed by a sem_wait
is likely to result in the same thread grabbing the semaphore right away (on a single cpu system). I'm surprised that pthread_yield
doesn't help, but using two semaphores will guarantee correct ordering no matter what.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With