简体   繁体   中英

How to print from each thread in pthreads in order?

I'm working on a program for class that takes a Floyd-Warshall directed graph (represented by a matrix) and makes a new distance matrix for each node in the graph, splitting the work of creating the new matrix among threads using pthreads. I feel that I am right at the end, I can get the matrix to form and print, but I can't seem to figure out how to get the distance matrix to print in order (lines of matrix created by thread 0 first, then thread 1, thread 2, etc). I use the mutex to allow each thread to print its part together without interruption, I just can't get the threads to print in order.

I was wondering if a pthread guru out there would help me out. Thanks in advance!

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

int n, totaln, **C, **D;                    /* Variable declarations */
pthread_t *threads;
pthread_mutex_t mutexprint;
long thread, threadcount;

void *LowestTerm(void* rank);

int main(int argc, char *argv[]) {

    int i, j, k;                        /* Variable declarations */
    char filename[50];

    threadcount = atoi(argv[1]);
    threads = malloc (threadcount * sizeof(pthread_t));

    printf("Enter filename: ");             /* User enters filename for directed graph values */
    scanf("%s", filename);

    FILE *fp = fopen(filename, "r");

    if (fp == NULL) {                   /* Check whether file exists or not */
        printf("File does not exist");
        return 1;
    }

    fscanf(fp, "%d", &n);                   /* Obtain size of matrix */

    totaln = n * n;

    C = (int **)malloc(n * sizeof(int *));          /* Allocate memory for matrix arrays */
    D = (int **)malloc(n * sizeof(int *));

    for (i = 0; i < n; i++) {               /* Allocate matrices into 2D arrays */
        C[i] = (int *)malloc(n * sizeof(int));
        D[i] = (int *)malloc(n * sizeof(int));
    }


    for (i = 0; i < n; i++) {               /* Read matrix from file into C array */
        for (j = 0; j < n; j++) {
            fscanf(fp, "%d", &C[i][j]);
        }
    }

    printf("Cost Adjacency Matrix:\n");         /* Print cost adjacency matrix */
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            printf("%d ", C[i][j]);
        }
        printf(" \n");
    }

    for (i = 0; i < n; i++) {               /* Copy matrix from C array into D array */
        for (j = 0; j < n; j++) {
            D[i][j] = C[i][j];
        }
    }

    printf("Distance matrix:\n");



    for (thread = 0; thread < threadcount; thread++) {
        pthread_create(&threads[thread], NULL, LowestTerm, (void*) thread);
    }
    for (thread = 0; thread < threadcount; thread++) {
        pthread_join(threads[thread], NULL);
    }

    pthread_mutex_destroy (&mutexprint);
    free(threads);
    pthread_exit(NULL);

}


void *LowestTerm(void* rank) {

    int i, j, k;                        /* Variable declarations */
    long mythread = (long) rank;

    int istart = ((int)mythread * n) / (int)threadcount;    /* Create matrix row start and finish parameters for each thread */
    int ifinish = ((((int)mythread + 1) * n) / (int)threadcount);

    for (k = 0; k < n; k++) {               /* Find shortest path for each value in each row for each of designated thread's rows */
        for (i = istart; i < ifinish; i++) {
            for (j = 0; j < n; j++) {
                if (D[i][j] > D[i][k] + D[k][j]) {
                    D[i][j] = D[i][k] + D[k][j];
                }
            }
        }
    }

    pthread_mutex_lock (&mutexprint);           /* Print distance matrix */
    for (i = istart; i < ifinish; i++) {
        printf("Thread %d: ", mythread);
        for (j = 0; j < n; j++) {
            printf("%d ", D[i][j]);
        }
        printf(" \n");
    }
    pthread_mutex_unlock (&mutexprint);


    return NULL;
}

The simplest solution is just to have your main thread print the entire matrix in the order you want, once all the worker threads have finished.


Alternatively, to have your threads print in order you can use a shared variable specifying the next thread to print (initialised to 0), paired with a condition variable:

pthread_mutex_lock (&mutexprint);           /* Print distance matrix */
while (next_thread != mythread)
    pthread_cond_wait(&condprint, &mutexprint);

for (i = istart; i < ifinish; i++) {
    printf("Thread %d: ", mythread);
    for (j = 0; j < n; j++) {
        printf("%d ", D[i][j]);
    }
    printf(" \n");
}

next_thread++;
pthread_cond_broadcast(&condprint);
pthread_mutex_unlock (&mutexprint);

As a separate matter, I don't think your threads safely share the D[] array - it looks like the read from D[k][j] could be reading a position that is being simultaneously written by another thread.

since each thread has a parameter that indicates its' rank,
the mutex could be on a global variable that indicates 
which thread/rank is to print next.
initialize it to 0.
each thread reads the global variable, after the thread
is ready to print
when the global variable matches the threads' rank, 
then the thread can:
1) lock the mutex, 
2) print, 
3) increment the global variable, 
4) unlock the mutex
5) call pthread_exit()

BTW: why are thread and threadcount defined as 'long'?
are you expecting there to be more than 4 gig threads?

at the end of function: LowestTerm()
which is a thread function.
the proper exit is not 'return value;'\
but rather phread_exit( value );

'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM