Чтение файла с использованием нескольких потоков

Я хочу проверить список ips, если они находятся в черном списке (используя многопоточность).

Итак, у меня есть следующий код:

pthread_mutex_t input_queue;

void * process(void * data)
{
    unsigned long ip = 0xffffffff;
    char line[20];
    while (!feof(INFILE))
    {
        pthread_mutex_lock(&input_queue);//?required
        if (fgets(line,sizeof(line),INFILE) != NULL)
        {
            if (strlen(line) < 8)
                break;
            if (line[strlen (line) - 1] == '\n')
                line[strlen (line) - 1] = '\0';
            ip = ntohl((unsigned long)inet_addr(line));
        }
        pthread_mutex_unlock(&input_queue);
        blacklist(ip);
    }
    return NULL;
}

//in main()
    pthread_mutex_init(&input_queue,NULL);
    for(i = 0 ; i < number_thread; i++)
    {
        if(pthread_create(&thread_id[i],NULL,&process,NULL) != 0)
        {
            i--;
            fprintf(stderr,RED "\nError in creating thread\n" NONE);
        }
    }
    for(i = 0 ; i < number_thread; i++)
        if(pthread_join(thread_id[i],NULL) != 0)
        {
            fprintf(stderr,RED "\nError in joining thread\n" NONE);
        }

Нужен ли pthread_mutex_lock или fgets безопасен для потоков? У меня такое чувство, что у моего кода есть некоторые проблемы.

2 ответа

Решение

Тебе это не нужно. POSIX гарантирует, что каждый FILE Объект является потокобезопасным. См. http://pubs.opengroup.org/onlinepubs/009695399/functions/flockfile.html:

Все функции, которые ссылаются (FILE *) объекты должны вести себя так, как будто они используют flockfile() а также funlockfile() внутренне, чтобы получить право собственности на эти (FILE *) объекты.

Если не blacklist(ip) требует значительных вычислений, блокировка каждые 10 байтов фактически сделает ваше приложение намного медленнее, чем полное отсутствие многопоточности.

C.99 не поддерживает потоки, поэтому для переносимости потребуется наличие блокировок. Тем не менее, C.11 дает гарантии безопасности потоков при файловых операциях (C.11 §7.21.2 ¶7):

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

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

Другие вопросы по тегам