Pthread_join Printf

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

file1: line 1
file1: line 2
file2: line 1

и так далее. Я мог бы решить эту проблему, используя глобальный массив 2d и создав структуру для передачи потоку его «id» и имени текстового файла, который он должен искать. Я использовал pthread_join, и это довольно интуитивно понятно. Проблема в следующей задаче, решите ту же задачу, но без pthread_join и без занятого ожидания, если это возможно. Проблема в том, что если я не использую pthread_join, я не могу ничего напечатать в функции потока, и я этого не ожидал? Есть ли причина, по которой это происходит?

Это код, который я использовал для решения проблемы с pthread_join. Без pthread_join, используя мьютекс и пытаясь напечатать вывод в функции потока, я не получил вывода.

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<errno.h>
#include<fcntl.h>
#include <pthread.h>
#define k 4
#define l 100

int match_line(int fd, char *str);
void *ocorre(void *);

char string[100];
int b[k][l];
int max;

struct args{
    char str[256];
    int id;
};
int main(int argc, char *argv[]){

    int i=0;
    int j=0;
    max=argc-1;

    struct args arg[max];
    pthread_t a[max];

    strcpy(string,argv[1]); //global

    for(i=0;i<max-1;i++){   //criaçao de threads
        arg[i].id=i;
        strcpy(arg[i].str,argv[i+2]);
        pthread_create(&a[i],NULL,ocorre,&arg[i]);
    }

    for(i=0;i<max-1;i++){ //join
        pthread_join(a[i],NULL);
            for(j=0;b[i][j]!=0;j++){
                printf("%s : %d\n",arg[i].str,b[i][j]);
            }
    }
}
void *ocorre(void *arg) {

    int fd;
    int j=0;
    struct args func;
    func=*(struct args*)arg;

    fd=open(func.str,O_RDONLY);
        while(1){
        b[func.id][j]=match_line(fd,string);
            if(b[func.id][j]==0) 
                break;
        j++;
    }

    return NULL;
}

Это то, что я пытался решить без pthread_join. Чтобы получить первый вывод, я должен добавить sleep(1) после создания потока


person Luce Sky Walker    schedule 13.04.2017    source источник
comment
Мы не можем найти ошибку в коде, которого не видим. Но вы можете использовать другой механизм синхронизации (например, мьютекс, условную переменную и предикатную переменную), чтобы узнать, когда работа будет выполнена.   -  person David Schwartz    schedule 13.04.2017
comment
Я думаю, что понимаю, что происходит, это не ошибка. Если поток не может быть присоединен, я потеряю информацию, которая была изменена в функции потока?   -  person Luce Sky Walker    schedule 13.04.2017
comment
Нет, дело обстоит совсем не так. Вам просто нужно убедиться, что работа выполнена, прежде чем пытаться использовать ее результаты. (И использовать завершение потоков для обозначения завершения работы — плохая практика.)   -  person David Schwartz    schedule 13.04.2017
comment
Предлагается использовать pthread_join()   -  person Luce Sky Walker    schedule 13.04.2017
comment
Плохая практика использовать завершение потока как способ узнать, что работа была сделана. Нет причины, по которой код, который хочет дождаться завершения работы, должен заботиться о том, что поток, который выполняет работу, продолжает делать после того, как он закончил работу. Если вы хотите подождать, пока работа не будет сделана, дождитесь работы. Возможно, было предложено убедиться, что вы знаете, как работает pthread_join.   -  person David Schwartz    schedule 13.04.2017
comment
я ответил кодом, который я использовал для вопроса, что я могу использовать соединение pthread. Если я возьму часть соединения, использую мьютекс в функции потока и попытаюсь распечатать его, у него будет 0 выходных данных.   -  person Luce Sky Walker    schedule 13.04.2017
comment
Мой первый комментарий можно было бы расширить до ответа. У меня сейчас нет на это времени, но я мог бы через некоторое время, если никто другой этого не сделает. Используйте подходящую форму синхронизации, такую ​​как семафор или барьер.   -  person David Schwartz    schedule 13.04.2017
comment
Так или иначе, каждый поток должен будет сохранять результаты, чтобы какой-то поток (возможно, поток для каждого файла, возможно, основной поток) мог записать всю информацию для одного файла за одну операцию. Вы можете использовать flockfile(), чтобы обеспечить синхронизацию выходного потока. Поток блокирует выходной поток, записывает и разблокирует. Вы можете использовать мьютексы и условные переменные для каждого файла/потока без использования pthread_join(), но не забывайте запускать потоки как отдельные потоки, если вы не собираетесь к ним присоединяться.   -  person Jonathan Leffler    schedule 13.04.2017
comment
То, как я узнал, было с конд. переменные или мьютексы. Но проблема, с которой я сталкиваюсь, заключается в том, что с отдельными потоками у меня нет вывода, если я пытаюсь напечатать что-то в функции потока, я не думаю, что смогу даже получить к нему доступ, массив b вообще не изменяется, все 0, когда я пытаюсь распечатать его в основном   -  person Luce Sky Walker    schedule 13.04.2017
comment
Хорошо, я отсоединил его сразу после того, как создал. Если я немного задержу это действие, я получу вывод. Может ли это быть проблема? мне пришлось использовать функцию сна между созданием и отсоединением, чтобы получить вывод. Я не понимаю, почему, хотя   -  person Luce Sky Walker    schedule 13.04.2017
comment
Используйте второй параметр pthread_create, чтобы создать поток как отсоединенный, вместо того, чтобы создавать его как присоединяемый (по умолчанию), а затем отдельно отсоединять.   -  person bta    schedule 13.04.2017
comment
таким образом он ничего не напечатает. код точно такой же, только использование отдельных потоков, без phtread_join и печать в функции потока вместо основной, с использованием мьютексов   -  person Luce Sky Walker    schedule 13.04.2017
comment
я добавил изображение, показывающее код и результаты   -  person Luce Sky Walker    schedule 13.04.2017
comment
с pthread_exit в основном у меня есть вывод без использования сна. Почему это произошло?   -  person Luce Sky Walker    schedule 13.04.2017


Ответы (1)


Возврат из main завершает процесс, потому что это примерно эквивалентно вызову exit. У вас есть два варианта:

  1. Убедитесь, что main не возвращается или иным образом не завершается, пока вся работа не будет выполнена, или

  2. Позвоните phthread_exit в main, а не возвращайтесь.

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

person David Schwartz    schedule 13.04.2017