Синхронизация критического раздела C - PullRequest
0 голосов
/ 30 сентября 2019

Пытаясь реализовать критическую секцию этой программы, чтобы на самом деле правильно переключаться между обоими потоками, как указано далее в описании.

Я пытаюсь выполнить задачу для моего курса по операционным системам. Проблема в том, что мне нужно ввести два файла, каждый из которых помещается в отдельные потоки, они будут читать файл до тех пор, пока не попадут в строку с номером «0». Затем предполагается, что другой поток будет работать по тем же правилам.

Предполагается, что эта программа примет два файла ввода и определит сообщение, объединяя оба ввода из файлов в определенном порядке, а затем распечатывая их. вывод после того, как он расшифровал его.

Входные данные этих двух файлов, как показано ниже

Person1         Person2          
---------       ---------- 
t                  0
0                  h
i                  0
s                  0
0                  i
0                  s
0                  a
t                  0
e                  0
0                  s
t                  0

вышеупомянутые входные данные должны привести к строке с этим выводом

Пример: «thisisatest»

В настоящее время неправильно выполняется назначение, состоящее в том, что оно неправильно переставляется между двумя потоками и находится в бесконечных циклах.

Как я уже говорил выше, я пытаюсь решить это назначениес помощью Mutexes и Pthreads

Ниже приведена текущая реализация моего кода

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



static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static char *charArray[1000];

void *threadPerson1(void *value){

    FILE *fPTR;
    char buffer[2];

    char *fileName = "Person1.txt";

    fPTR = fopen(fileName, "r");

    if (fPTR == NULL){

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

    while(1){

        //Entering the critical section
        pthread_mutex_lock(&mutex);

        fscanf(fPTR, "%s", buffer);
        printf("This is Person1: %s\n", buffer);



        if(buffer != "0"){

            charArray[count] = buffer;
            count++;
        }
        if(buffer == "0"){

            pthread_mutex_unlock(&mutex);
        }
        //exiting the critical section
    }


}

void *threadPerson2(void *value){

    FILE *fPTR;
    char buffer[2];

    char *fileName = "Person2.txt";

    fPTR = fopen(fileName, "r");    

    if (fPTR == NULL){

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

    while(1){

        //entering the critical section
        pthread_mutex_lock(&mutex);

        fscanf(fPTR, "%s", buffer);
        printf("This is Person2: %s\n", buffer);



        if(buffer != "0"){

            charArray[count] = buffer;
            count++;
        }
        if(feof(fPTR)){

            printf("read end of file of: Person2\n");
            fclose(fPTR);
            return NULL;
        }
        if(buffer == "0"){

            pthread_mutex_unlock(&mutex);
        }
        //exiting the critical section


    }


}


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


    pthread_t thread1;
    pthread_t thread2;

    pthread_create(&thread1, NULL, threadPerson1, NULL);
    pthread_create(&thread2, NULL, threadPerson2, NULL);

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);


    for(int x = 0; x < 1000; x++){

        if(charArray[x] == NULL){

            printf("\n");
            break;
        }else{

            printf("%s", charArray[x]);
        }
    }

    return 0;
}

1 Ответ

1 голос
/ 01 октября 2019

Как минимум две вещи неверны в вашей программе. Прежде всего, если один поток освобождает мьютекс, вам не гарантируется, что планировщик разрешит запуск другого потока, освобождающий поток может очень хорошо продолжаться и сразу же снова получить мьютекс. Используйте условную переменную, прочитайте ее man-страницы. Кроме того, вот несколько примеров, в частности 4-8: Многопоточное руководство по программированию

Два, когда вы достигнете конца файла, вам нужно освободить мьютекс для очистки. Самый простой способ сделать это - то, что мы называем RAII в C ++, то есть использовать дескриптор ресурса, который освобождает мьютекс, когда объект дескриптора выходит из области видимости. Вы можете сделать аналогичные вещи в C, например, зарегистрировав функцию очистки, или 'goto' в конец функции с вызванным оттуда кодом очистки.

...