I came across the sample code.
assuming_order_of_execution_pitfall.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define N 4
void* hello(void* arg)
{
printf("Hello World from Thread%d\n", *(int*)arg);
return NULL;
}
int main()
{
pthread_t tid[N];
int i;
for(i = 0; i < N; i++)
{
pthread_create(&tid[i], NULL, hello, (void*)&i); //&i points to same address
}
for(i = 0; i < N; i++)
{
pthread_join(tid[i], NULL);
}
return 0;
}
Here, it mistakenly assumes that threads begin execution the moment they are created. The printf() statement may indeed be executed before the next call to pthread_create(), but the operating system is free to schedule the threads in any order. It is possible that all threads are created before any of them actually begin executing. Since all copies of arg point to the same address, which is changing in main(), the threads can print the same identification number.
I have tried to correct the above code by using a unique address to hold the identification number of each thread as given below
assuming_order_of_execution_workaround.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define N 4
void* hello(void* arg)
{
printf("Hello World from Thread%d\n", *(int*)arg);
return NULL;
}
int main()
{
pthread_t tid[N];
int tno[N];
int i;
/* Added code */
for(i = 0; i < N; i++)
{
tno[i] = i + 1;
}/* Added code */
for(i = 0; i < N; i++)
{
pthread_create(&tid[i], NULL, hello, (void*)(tno+i)); // providing unique address for each thread
}
for(i = 0; i < N; i++)
{
pthread_join(tid[i], NULL);
}
return 0;
}
Is my correction the right method? Could some one suggest me a more correct method if there is one?
Yes, that’s the right approach.