Reputation: 1277
I've wrote the following program. I expect that this function print 1, 2 sequentially but the program waits some time(for example 10 sec) and then prints all of the result.
here is the code:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<pthread.h>
void *thread_function(void *arg);
char message[] = "Hello World";
int run_now = 1;
int main()
{
int res;
pthread_t a_thread;
void *thread_result;
res = pthread_create(&a_thread, NULL, thread_function, (void *)message);
if (res != 0)
{
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
int print_count1 = 0;
while(print_count1++ < 20)
{
if (run_now == 1)
{
printf("1");
run_now = 2;
}
else
{
sleep(1);
}
}
printf("\nWaiting for thread to finish...\n");
res = pthread_join(a_thread, &thread_result);
if (res != 0)
{
perror("Thread join failed");
exit(EXIT_FAILURE);
}
printf("Thread joined. \n");
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg)
{
int print_count2 = 0;
while(print_count2++ < 20)
{
if (run_now == 2)
{
printf("2");
run_now = 1;
}
else
{
sleep(1);
}
}
}
i expect to 1, 2 be printed every 1 seconds, but program is waiting some times and then prints all of the string entirely. can anybody tell me what's the reason?
Upvotes: 0
Views: 110
Reputation: 70931
int run_now
is accessed concurrently and therefore its access needs to be protected.
To do so use a mutex for example:
...
int run_now = 1;
pthtread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int main()
{
...
while(print_count1++ < 20)
{
pthread_mutex_lock(&mutex);
int run_now_equals_1 = (run_now == 1);
if (run_now_equals_1)
{
printf("1");
run_now = 2;
}
pthread_mutex_unlock(&mutex);
if (!run_now_equals_1)
{
sleep(1);
}
}
...
}
void *thread_function(void *arg)
{
int print_count2 = 0;
while(print_count2++ < 20)
{
pthread_mutex_lock(&mutex);
int run_now_equals_2 = (run_now == 2);
if (run_now_equals_2)
{
printf("2");
run_now = 1;
}
pthread_mutex_unlock(&mutex);
if (!run_now_equals_2)
{
sleep(1);
}
}
}
Upvotes: 3
Reputation: 428
Well, there are a few problems with your program. First, printf
may buffer things internally, so you won't see them. This is probably what you refer to. You need to fflush
stdout
after each printf
. The more serious problem is that your program is wrong, as it uses a non-atomic, non-volatile variable for communication.
In your thread_function
, the compiler is free to move the load of run_now
out of the loop and only work with a register copy, hence the loop won't ever notice that another thread changed the value in memory. You should always use atomic intrinsics to access shared variables like this.
Upvotes: 1
Reputation: 3751
Use fprintf(stderr,"...")
instead of printf
, or add a fflush(stdout)
after each printf
.
This is because stout
is flushed only when OS decides to flush it, while stderr
is flushed as soon as fprintf
is called.
Upvotes: 1