0

I am building a program for a school assignment. It has the following requirements as shown below.

  • Must use Mutexes

  • Must use Pthreads

  • Create 5 threads with random synchronization (aka: running in a non-specific order)

  • Threads must be detached from the main thread

  • Each thread is going to read from a file and adjust the balance of a bank account, each with different input files.

This is the link to the actual assignment and what we need to be doing with it for a slightly more detailed set of information AssignmentTxtFile

What my main question is to solve the deadlocking problem I have encounter. I do not know how to approach this problem exactly, I understand that I need to figure out a way for it not to enter into multiple thread's critical sections at any given time. How am I going to do this while keeping the execution order random?

Here is the code that I currently have for this program.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>





pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;


float balance = 0;



void *thread1(void *value){

    FILE *fPTR;
    char buffer;
    float number;

    char *fileName = "data1.in";

    fPTR = fopen(fileName, "r");

    if (fPTR == NULL){

        printf("was unable to open: %s\n", fileName);
        return NULL;
    }

    while(1){



        //Critical Section of Thread1
        pthread_mutex_lock(&mutex1);
            fscanf(fPTR, "%c%f\n", &buffer, &number);

            if(buffer == '+'){

                balance += number;

            }
            if(buffer == '-'){

                balance -= number;
            }


            printf("Account balance of thread1 is: %f\n", balance);

            if(feof(fPTR)){

                fclose(fPTR);
                printf("end of data1.in");
                return NULL;
            }

            printf("end of while thread1\n");
        pthread_mutex_unlock(&mutex1);

        sleep(.3);
    }


}

void *thread2(void *value){

    FILE *fPTR;
    char buffer;
    float number;

    char *fileName = "data2.in";

    fPTR = fopen(fileName, "r");

    if (fPTR == NULL){

        printf("was unable to open: %s\n", fileName);
        return NULL;
    }

    while(1){



        //Critical Section of Thread2
        pthread_mutex_lock(&mutex1);
            fscanf(fPTR, "%c%f\n", &buffer, &number);

            if(buffer == '+'){

                balance += number;

            }
            if(buffer == '-'){

                balance -= number;
            }


            printf("Account balance of thread2 is: %f\n", balance);

            if(feof(fPTR)){

                fclose(fPTR);
                printf("end of data2.in");
                return NULL;
            }

            printf("end of while thread2\n");
        pthread_mutex_unlock(&mutex1);

        sleep(.3);
    }


}

void *thread3(void *value){

    FILE *fPTR;
    char buffer;
    float number;

    char *fileName = "data3.in";

    fPTR = fopen(fileName, "r");

    if (fPTR == NULL){

        printf("was unable to open: %s\n", fileName);
        return NULL;
    }

    while(1){



        //Critical Section of Thread3
        pthread_mutex_lock(&mutex1);
            fscanf(fPTR, "%c%f\n", &buffer, &number);

            if(buffer == '+'){

                balance += number;

            }
            if(buffer == '-'){

                balance -= number;
            }


            printf("Account balance of thread3 is: %f\n", balance);

            if(feof(fPTR)){

                fclose(fPTR);
                printf("end of data3.in");
                return NULL;
            }

            printf("end of while thread3\n");
        pthread_mutex_unlock(&mutex1);

        sleep(.3);
    }


}

void *thread4(void *value){

    FILE *fPTR;
    char buffer;
    float number;

    char *fileName = "data4.in";

    fPTR = fopen(fileName, "r");

    if (fPTR == NULL){

        printf("was unable to open: %s\n", fileName);
        return NULL;
    }

    while(1){



        //Critical Section of Thread4
        pthread_mutex_lock(&mutex1);
            fscanf(fPTR, "%c%f\n", &buffer, &number);

            if(buffer == '+'){

                balance += number;

            }
            if(buffer == '-'){

                balance -= number;
            }


            printf("Account balance of thread4 is: %f\n", balance);

            if(feof(fPTR)){

                fclose(fPTR);
                printf("end of data4.in");
                return NULL;
            }

            printf("end of while thread4\n");
        pthread_mutex_unlock(&mutex1);

        sleep(.3);
    }


}

void *thread5(void *value){

    FILE *fPTR;
    char buffer;
    float number;

    char *fileName = "data5.in";

    fPTR = fopen(fileName, "r");

    if (fPTR == NULL){

        printf("was unable to open: %s\n", fileName);
        return NULL;
    }

    while(1){



        //Critical Section of Thread5
        pthread_mutex_lock(&mutex1);
            fscanf(fPTR, "%c%f\n", &buffer, &number);

            if(buffer == '+'){

                balance += number;

            }
            if(buffer == '-'){

                balance -= number;
            }


            printf("Account balance of thread5 is: %f\n", balance);

            if(feof(fPTR)){

                fclose(fPTR);
                printf("end of data5.in");
                return NULL;
            }


            printf("end of while thread5\n");
        pthread_mutex_unlock(&mutex1);

        sleep(.3);
    }


}




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



    pthread_t pthread1;
    pthread_t pthread2;
    pthread_t pthread3;
    pthread_t pthread4;
    pthread_t pthread5;



    pthread_create(&pthread1, NULL, thread1, NULL);
    pthread_create(&pthread2, NULL, thread2, NULL);
    pthread_create(&pthread3, NULL, thread3, NULL);
    pthread_create(&pthread4, NULL, thread4, NULL);
    pthread_create(&pthread5, NULL, thread5, NULL);


    pthread_detach(pthread1);
    pthread_detach(pthread2);
    pthread_detach(pthread3);
    pthread_detach(pthread4);
    pthread_detach(pthread5);

    printf("main completed\n");

    pthread_exit(0);



}
Felauras
  • 71
  • 9
  • Tip: Use the same thread func for each thread. Pass the file name as an argument. – ikegami Oct 13 '19 at 06:26
  • 1
    Re "*What my main question is to solve the deadlocking problem*", What deadlock? – ikegami Oct 13 '19 at 06:27
  • Tip: Reduce the code protected by your mutex to a bare minumum. – ikegami Oct 13 '19 at 06:28
  • Well, I would but in the requirements of the actual file it says that it wants the programmer to actually show what thread is being used at the time when an operation is completed – Felauras Oct 13 '19 at 06:28
  • You could pass the thread number as an argument, or you could use [the thread's unique id](https://stackoverflow.com/questions/21091000/how-to-get-thread-id-of-a-pthread-in-linux-c-program). There's no excuse for having 5 nearly identical functions. – ikegami Oct 13 '19 at 06:29
  • Actually I have figured out why this was deadlocking, it was because of the position of the end of file check. needed to take out of the critical section because it was breaking that thread before it could then unlock the mutex. – Felauras Oct 13 '19 at 06:35
  • So, how would you go about sending the arguments? I suppose i could do so with sending in an Array of strings? with one index being the thread number and then the other being the names of the data files? – Felauras Oct 13 '19 at 06:37
  • Using `pthread_create`'s fourth argument. Sure, you could simply send an index into a global array. (If all you want to pass is an index, cast it to `void*` in `main`, then cast it to `intptr_t` in the thread sub. – ikegami Oct 13 '19 at 07:03

1 Answers1

1

Simple answer to this question as to why it was deadlocking or never entering the critical sections was the position of the end of file checks, they needed to be taken outside of the critical section and within the while loops.

This caused the threads to never finish due to the fact that they were never able to unlock a mutex and then not able to ever actually enter into a critical section.

Felauras
  • 71
  • 9
  • Re "*was deadlocking or never entering the critical sections*", The latter. A *deadlock* and when tread A is blocked waiting for a resource held by thread B, and B is blocked waiting for a resource held by A. What you had was an extreme case of *thread starvation*. – ikegami Oct 13 '19 at 06:58
  • Re "*was deadlocking or never entering the critical sections*", The latter. A *deadlock* and when tread A is blocked waiting for a resource held by thread B, and B is blocked waiting for a resource held by A. You can't possibly have a deadlock if there's only one shared resource (the mutex, in your case). What you had was an extreme case of *thread starvation*. – ikegami Oct 13 '19 at 07:05