Синхронизация чтения файлов Mutex - PullRequest
0 голосов
/ 16 октября 2018

Я пытаюсь синхронизировать чтение 5 файлов, чтобы каждый символ читался из файла, а затем из следующего файла другой символ и так далее.В конце массив распечатает содержимое.Я могу читать из файлов, но синхронизация еще не завершена.Я попытался исправить это с помощью управляющей переменной, чтобы запускать блок кода только тогда, когда файлы поворачиваются, но я получаю шаткий выводВот мой раздел, в котором я работаю над критическими разделами

while(!feof(drive1)) {
        if(control == 0) {
            pthread_mutex_lock(&thread1);
            //printf("Mutex lock\n");
            c = getc(drive1);
            printf("%c", (char)c);
            control = 1;
            pthread_mutex_unlock(&thread1);
            //printf("Mutex unlock\n");
        } else if(control == 1) {
            pthread_mutex_lock(&thread2);
            //printf("Mutex lock\n");
            a = getc(drive2);
            printf("%c", (char)a);
            control = 2;
            pthread_mutex_unlock(&thread2);
            //printf("Mutex unlock\n");
        } else if(control == 2) {
            pthread_mutex_lock(&thread3);
            //printf("Mutex lock\n");
            b = getc(drive3);
            printf("%c", (char)b);
            control = 3;
            pthread_mutex_unlock(&thread3);
            //printf("Mutex unlock\n");
        } else if(control == 3) {
            pthread_mutex_lock(&thread4);
            //printf("Mutex lock\n");
            d = getc(drive4);
            printf("%c", (char)d);
            control = 4;
            pthread_mutex_unlock(&thread4);
            //printf("Mutex unlock\n");
        } else if(control == 4) {
            pthread_mutex_lock(&thread5);
            //printf("Mutex lock\n");
            e = getc(drive5);
            printf("%c", (char)e);
            control = 0;
            pthread_mutex_unlock(&thread5);
            //printf("Mutex unlock\n");
        }

Сначала я попробовал сделать это, используя только один поток1, используемый для блокировки мьютексов и их разблокировки, но затем решил создать 5, чтобы посмотреть, поможет ли это, но это не так.Я также должен использовать 5 потоков, чтобы сделать это для каждого из файлов.

pthread_t th1;
    pthread_create(&th1, NULL, processing, NULL);
    pthread_t th2;
    pthread_create(&th2, NULL, processing, NULL);
    pthread_t th3;
    pthread_create(&th3, NULL, processing, NULL);
    pthread_t th4;
    pthread_create(&th4, NULL, processing, NULL);
    pthread_t th5;
    pthread_create(&th5, NULL, processing, NULL);
    pthread_join(th1, NULL);
    pthread_join(th2, NULL);
    pthread_join(th3, NULL);
    pthread_join(th4, NULL);
    pthread_join(th4, NULL); 

Это вывод, который я получаю enter image description here

И вывод должен быть "1234567890abcdefghij"

ОБНОВЛЕНИЕ: На основеВ одном из комментариев я изменил код, чтобы использовать переменную «test» в качестве того, что тестируется в критическом разделе.С этим кодом я получаю вывод 1212.

void* disk1(void* args) {
    //Initializing array of files
    FILE *drive[5];

    drive[0] = fopen("drive1.data", "r");
    drive[1] = fopen("drive2.data", "r");
    drive[2] = fopen("drive3.data", "r");
    drive[3] = fopen("drive4.data", "r");
    drive[4] = fopen("drive5.data", "r");


    int c;

    if(test < initialFileSize * 2) {
        pthread_mutex_lock(&thread1);
        if(test % 2 == 0) {
            c = getc(drive[0]);
            printf("%c", (char)c);
            test++;
        }
        if(test % 2 == 1) {
            c = getc(drive[1]);
            printf("%c", (char)c);
            test++;
        }
        pthread_mutex_unlock(&thread1);
    }
}

Ответы [ 2 ]

0 голосов
/ 17 октября 2018

Есть несколько моментов, которые необходимо учитывать:

  • if (control == 0): условие if неверно установлено.Когда потоки начинают выполнять функцию, счетчик равен 0. Таким образом, наиболее вероятно, что в условие входит более одного потока.
  • На следующей строке вы блокируете мьютекс.Но могут быть потоки, которые уже вошли в условие if.Mutext только заставляет потоки выполнять следующие строки одну за другой.Таким образом, один за другим каждый поток входит и читает с drive1 и печатает первый символ.По этой причине вы получаете вывод «11111»
  • То же самое верно и для других операторов, если вы получаете вывод «111112222233333 ...»
  • while (! Feof (drive1)): Условие while проверяет конец файла на диске1.В зависимости от количества символов в drive1, это будет цикл.Вместо этого проверка отдельных файлов или проверка общего количества печатаемых символов даст более точный результат.

Несколько баллов могут помочь:

  • Mutex или любая другая блокировка используется для синхронизации доступа к общему ресурсу или переменной или блоку кода.Может быть несколько потоков, пытающихся получить доступ к блоку кода или переменной / ресурсу.Однако количество необходимых мьютексов зависит от количества переменных или кодовых блоков, которые вы хотите синхронизировать.
  • В этом случае ожидаемый результат представляет собой определенную последовательность.Это может быть достигнуто путем синхронизации доступа ко всему блоку, где проверяется значение счетчика, а конкретный файл считывается и записывается в стандартный вывод.Итак, у нас есть один блок кода в качестве критической секции, и нам нужен один мьютекс.
  • При защите общей переменной / ресурса, который используется в нескольких функциях.Нам нужно использовать один мьютекс для защиты одной переменной / ресурса во всех функциях.

Пожалуйста, заблокируйте мьютекс перед проверкой условия if (control == 0) и разблокируйте после завершения последней, если if.Будет синхронизирован доступ к блоку кода.Также необходимо изменить условие while (! Feof (drive1)).

Ниже приведен один из способов ее решения.

  • Я использовал общее количество символов, которые будут напечатаны в состоянии условия.
  • Использовал «total» как переменную переменной.
  • Снова проверяя значение «total» внутри цикла while, возможно, значение total изменяется, когда поток попадает в критическую секцию..
  • С этим решением возможно, что та же самая нить может снова получить блокировку и вывести значения.

            while(total < TOTAL_CHAR_TO_PRINT)
            {
                    pthread_mutex_lock(&m1);
                    if(total >= TOTAL_CHAR_TO_PRINT)
                    {
                            pthread_mutex_unlock(&m1);
                            return 0;
                    }
    
                    counter = counter % NUM_OF_FILES;
                    d = fgetc(fptr[counter]);
                    printf("%c", d);
    
                    counter += 1;
                    total += 1;
    
                    pthread_mutex_unlock(&m1);
            }
    
0 голосов
/ 16 октября 2018

вы можете синхронизировать их с одним флагом, но они будут тратить большую часть времени на ожидание, так что это, вероятно, не оптимально:

char shouldRead(){
  static unsigned int activeThread = 0; //used as index into the file to read and the thread compare.
  char x = 0;

  //wait for mutex
  pthread_mutex_lock(&readVariableMutex);
  //acquired mutex

  //read variable to see what thread should run
  if(availableThreads[activeThread] == myThreadId){
    x = getc(drive[activeThread]); //or w/e your doing when it should run
    activeThread++;
    activeThread %= MAX_THREADS; //should be 5 right
  }

  pthread_mutex_unlock(&readVariableMutex);
  return x;
}

//where ever you spawn your threads add them to a global availableThreads[MAX_THREADS] array;
//Also, when you intialize your FILE *'s, add them to a drive array.
//The above idea is to wrap access to variable "activeThread" around the mutex such that the controlling thread will always be the next thread, or it will do nothing and release the mutex.

Все потоки будут иметь что-то вроде:

while(!eof(drive[thead_id])){ //Each thread needs to know when its at end of file somehow
  printf("%c",shouldRead());
}
...