2015-04-11 2 views
-2

Я как бы знаком с многопоточным C/Linux, но на этот раз мне нужно сделать некоторую работу с C++ в Windows, но я не мог ее разглядеть. В моей программе у меня есть 2 функции, которые постоянно пытаются достичь одного и того же файла, чтобы сделать некоторые операции печати, и что происходит, один из них никогда не работает, что заставляет меня думать, что функция никогда не может открыть файл, потому что другая всегда может писать на нем. Как я могу реализовать потоки, чтобы сделать эту работу? Код выглядит примерно так:C++ многопоточность и мьютексы

std:mutex mut; 
    main(){ 
     while(1){ 
      //get mychar from user 
      print1(mychar, "my.txt"); 
      print2(); 
     } 
    } 

print1(int i, char* file){ 
    FILE *f = fopen(file, "a"); 
    /*print operations 
    .. 
    .*/ 
    fclose(f); 
    return 0; 
} 

void print2(){ 
    /*getting a string 
    ... 
    Sleep(200); 
    getting another string 
    ...*/ 
    char getX[]; //fill buffers with the strings accordingly 
    char getY[]; //basically i want to know if the initial string has changed 
    if(*getX != *getY){ 
     std::Lock_guard<std::mutex> guard(mut); 
     FILE *f = fopen("my.txt", "a"); 
     fprintf(f, "%s ", getY); 
     fclose(f); 
    } 
    getX = NULL; 
    getY = NULL; 
} 
+0

Что такое 'a' здесь:' FILE * f = fopen ("my.txt", a); '? – huu

+0

О, я имел в виду '' '' 'для режима добавления. Я сразу же отредактирую – gadria

+0

, почему нет мьютекса в print1? и я считаю, что вам нужно делать fopen также в охраняемом регионе –

ответ

3

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

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

std::mutex mut; 

main(){ 
    while(1){ 
     //get mychar from user 
     print1(mychar, "my.txt"); 
     print2(); 
    } 
} 

print1(int i, char* file){ 
    std::lock_guard<std::mutex> guard(mut); 
    FILE *f = fopen(file, "a"); 
    /*print operations 
    .. 
    .*/ 
    fclose(f); 
    return 0; 
} 

void print2(){ 
    /*getting a string 
    ... 
    Sleep(200); 
    getting another string 
    ...*/ 
    char getX[]; //fill buffers with the strings accordingly 
    char getY[]; //basically i want to know if the initial string has changed 
    if(*getX != *getY){ 
     std::lock_guard<std::mutex> guard(mut); 
     FILE *f = fopen("my.txt", "a"); 
     fprintf(f, "%s ", getY); 
     fclose(f); 
    } 
    getX = NULL; 
    getY = NULL; 
} 

Как кто-то отметил, что вы даже не используя параллелизм здесь. Это только один вызов функции за другим. Если вы хотите использовать темы, вы можете сделать это в while(1) цикле:

while(1){ 
    std::thread thread1(print1, mychar, "my.text"); 
    std::thread thread2(print2); 
    thread1.join(); 
    thread2.join(); 
} 

Edit: Я редактировал свой print2 функцию, чтобы открыть файл только тогда, когда нужно писать в него. Это делает параллелизм более разумным в структуре вашего приложения.

+0

'mychar' должен быть целым или явно отбрасываться в один. – huu

+0

Скомпилировано, но я не вижу никакого вывода из print2 и после нескольких входов для печати1 программа начинает отставать, и я теряю некоторые входы. 'mychar' имеет тип' char'. Я передаю целое число в char, и это мой вывод. Меня не интересует целочисленное значение. – gadria

+0

Проблема заключается в строке 'if (* getX! = * GetY)'. Это будет возвращать false каждый раз, потому что вы инициализируете 'getX' и' getY', не изменяя их прямо перед условным. – huu