How to synchronize threads?
I used threads in this code. but when I execute this code in shell, some threads didn't print this line.
printf("\ti'm %dth thread:)", j); 开发者_开发知识库
printf("\t%c %d %d %d \n", arr[j].op, arr[j].byte, seq, no_file);
In addition, even some threads print this line twice. what happened to this process? And how to reorganize this code in order to threads print the line exactly once?
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
typedef struct {char op; int byte; int seq; int no_file; } ARRAY;
ARRAY *arr;
void *thread_operation(void *arg){
int j =*((int*)arg);
seq = arr[j].seq;
int no_file = arr[j].no_file;
printf("\ti'm %dth thread:)", j);
printf("\t%c %d %d %d \n", arr[j].op, arr[j].byte, seq, no_file);
}
int main()
{
int err, j, i = 10;
long int tid;
arr = (ARRAY*)malloc(sizeof(ARRAY) * i);
srand(time(NULL));
for (i = 0; i <= 10; i++){
arr[i].op = 'r';
arr[i].byte = (rand() % 10);
arr[i].seq = i;
arr[i].no_file = i + 10;
}
for(j = 0; j < 10; j++){
printf("creating %dth thread.....", j);
err = pthread_create(&tid, NULL, thread_operation, &j);
if(err != 0)
printf("%s\n", strerror(err));
printf("%dth done\n", j);
}
return 0;
}
This is result from my pc
creating 0th thread.....0th done
creating 1th thread..... i'm 0th thread:) r 9 0 10
1th done
creating 2th thread..... i'm 2th thread:) r 3 2 12
i'm 2th thread:) r 3 2 12
2th done
creating 3th thread..... i'm 3th thread:) r 6 3 13
3th done
creating 4th thread..... i'm 4th thread:) r 9 4 14
4th done
creating 5th thread..... i'm 5th thread:) r 3 5 15
5th done
creating 6th thread..... i'm 6th thread:) r 2 6 16
6th done
creating 7th thread..... i'm 7th thread:) r 2 7 17
7th done
creating 8th thread.....8th done
creating 9th thread..... i'm 8th thread:) r 6 8 18
9th done
i'm 9th thread:) r 8 9 19
i'm 9th thread:) r 8 9 19
You need to use mutexes ton avoid race conditions, and you also need to use pthread_join to synchronize all your threads before the process dies.
Mutexes allow you to stop some threads while one of them is executing an action using a shared ressource (see man pthread_mutex_lock, pthread_mutex_init)
pthread_join is essential in your code, because it forces your main thread to wait for the other threads you created, if you don't use it, you're not sure all threads will be finished when the main thread returns from the main.
The reason why some are printing out twice (such as thread number 9) is because you are passing a pointer to your loop variable as the input to the thread_operation.
for(j = 0; j < 10; j++){
err = pthread_create(&tid, NULL, thread_operation, &j);<---here
that &j is eventually dereferenced by thread_operation:
void *thread_operation(void *arg){
int j =*((int*)arg);<---here
but at this point the loop could have advanced and the value of j (in the thread operation) will be whatever j happens to be in the loop right now. The way to fix this is to not pass a pointer but the value of j to the thread constructor. Change your pthread_create to pass the value:
pthread_create(&tid, NULL, thread_operation, (void*) j);
and in your thread cast the value out of the thread argument:
int j =(int)arg;
Now technically this relies on the fact that int
and void*
are the same size when in general they are not. But this will work as long as you aren't using giant int
values.
for all the other problems @Intrepidd is right about using pthread_join to make sure that the process doesn't exit before all your threads complete.
Using printf
with incomplete lines between threads will usually not work. You may get the output completely mangled. Also the order in which lines appear on your screen will in general not be the execution order but the order the threads access the shared resource stdout
.
精彩评论