How to synchronize streams?

I used streams in this code. but when I execute this code in the shell, some threads did not 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 so that threads print a 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 the result of my computer.

 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 
+4
source share
3 answers

You need to use mutexes to avoid race conditions, and you also need to use pthread_join to synchronize all your threads before the process completes.

Mutexes allow you to stop some threads while one of them performs an action using the resource share (see man pthread_mutex_lock, pthread_mutex_init)

pthread_join is needed in your code because it makes your main thread wait for other threads you created, if you are not using it, you are not sure that all threads will be completed when the main thread returns from the Main one.

+6
source

The reason some of them print twice (e.g., number 9) is because you are passing a pointer to your loop variable as an input to 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 be extended, and the value of j (in the thread operation) would be that j is in the loop right now. The way to fix this is not to pass a pointer, but a j value to the stream constructor. Modify pthread_create to pass the value:

 pthread_create(&tid, NULL, thread_operation, (void*) j); 

and in your thread, deduce the value from the stream argument:

 int j =(int)arg; 

Now technically it depends on the fact that int and void* are the same size when they are not at all. But this will work until you use gigantic int values.

for all other problems, @Intrepidd is right about using pthread_join to make sure that the process does not end before all of your threads are complete.

+2
source

Using printf with incomplete lines between threads usually doesn't work. You can get the result completely crippled. Also, the order in which lines are displayed on your screen, in general, will not be the order of execution, but the order in which threads will access the stdout .

+1
source

All Articles