многопоточность обрабатывает данные из одного файла - PullRequest
1 голос
/ 28 декабря 2010

Может ли кто-нибудь на этом форуме привести пример на C, как два потока обрабатывают данные из одного текстового файла.

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

спасибо

Ответы [ 3 ]

2 голосов
/ 28 декабря 2010

Если бы вы спросили в C ++, я мог бы дать вам пример кода, но я не делал ANSI C в течение очень долгого времени, поэтому я дам вам дизайн и псевдокод.

Пожалуйста, имейте в виду, что это действительно плохой псевдокод, предназначенный для примера. Я не спрашиваю, ПОЧЕМУ вы хотели бы сделать это. Насколько я знаю, это может быть упражнение с темами или потому, что вам «хочется».

Пример 1

int integerCount = 0;
int lineCount = 0;

numericThread()
{
    // By flagging the file as readonly you should
    // be able to open it as many times as you wish
    handle h = openfile ("textfile.txt". readonly);

    while (!eof(h)) {
          String word = readWord (h);
          int outInteger
          if (stringToInteger(word, outInteger)) {
                ++integerCount;
          }
    }
}

lineThread()
{
    // By flagging the file as readonly you should
    // be able to open it as many times as you wish
    handle h = openfile ("textfile.txt". readonly);

    while (!eof(h)) {
          String word = readWord (h);
          if (word.equals("\n") {
                ++lineCount ;
          }
    }
}

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

Пример 2

int integerCount = 0;
int lineCount = 0;
queue numericQueue;
queue lineQueue;

numericThread()
{

    while (!numericQueue.closed()) {
          String word = numericQueue.pop();
          int outInteger
          if (stringToInteger(word, outInteger)) {
                ++integerCount;
          }
    }
}

lineThread()
{
    while (!lineQueue.closed()) {
          String word = lineQueue.pop();
          if (word.equals("\n") {
                ++lineCount ;
          }
    }
}

mainThread()
{
    handle h = openfile ("textfile.txt". readonly);
    while (!eof(h)) {
          String word = readWord(h);
          numericQueue.push(word);
          lineQueue.push(word);
    }
    numericQueue.close();
    lineQueue.close();
}
2 голосов
/ 28 декабря 2010

Есть много способов сделать это.Вы можете принимать различные дизайнерские решения в зависимости от того, насколько быстрым, простым, элегантным или сверхмощным вы хотите, чтобы это было.Один из способов, заявленный Эндрю Финнеллом, состоит в том, чтобы каждый поток открыл файл и прочитал его полностью независимо.Теоретически это не очень хорошо, потому что вы делаете дорогой ввод-вывод дважды, но на практике это, вероятно, хорошо, потому что ОС, вероятно, кэшировала содержимое того, что считывание выполняется первым.Двойной ввод-вывод все еще дороже, чем в среднем, потому что он включает в себя множество ненужных системных вызовов, но опять же на практике это будет неактуально, если у вас нет очень большого файла.

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

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

0 голосов
/ 28 декабря 2010

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

PS Возможно, что в зависимости от размера файла вы действительнопотеря производительности при использовании 2 потоков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...