Несколько потоков, читающих из того же файла

Вы передаете Console.WriteLine объект Ienumerable:

Console.WriteLine(resultList); 

Но вы не хотите печатать элемент объекта (контейнер), но каждый элемент, поэтому вам нужно повторить результат и напечатать каждый из них:

foreach(var element in resultList)
    Console.WriteLine(element);
10
задан StaxMan 5 May 2009 в 06:00
поделиться

11 ответов

Если вы этого не сделаете t писать в них, не нужно заботиться о состоянии синхронизации / гонки.

Просто откройте файл с общим чтением как разные дескрипторы, и все будет работать. (т. е. вы должны открыть файл в контексте потока, а не использовать один и тот же дескриптор файла).

#include <stdio.h>
#include <windows.h>

DWORD WINAPI mythread(LPVOID param)
{
    int i = (int) param;
    BYTE buf[1000];
    DWORD numread;

    HANDLE h = CreateFile("c:\\test.txt", GENERIC_READ, FILE_SHARE_READ,
        NULL, OPEN_EXISTING, 0, NULL);

    SetFilePointer(h, i * 1000, NULL, FILE_BEGIN);
    ReadFile(h, buf, sizeof(buf), &numread, NULL); 
    printf("buf[%d]: %02X %02X %02X\n", i+1, buf[0], buf[1], buf[2]);

    return 0;
}

int main()
{
    int i;
    HANDLE h[4];

    for (i = 0; i < 4; i++)
        h[i] = CreateThread(NULL, 0, mythread, (LPVOID)i, 0, NULL);

    // for (i = 0; i < 4; i++) WaitForSingleObject(h[i], INFINITE);
    WaitForMultipleObjects(4, h, TRUE, INFINITE);

    return 0;
}
21
ответ дан 3 December 2019 в 15:06
поделиться

Нет даже большой проблемы с записью в один и тот же файл, если честно.

Безусловно, самый простой способ - просто отобразить файл в памяти. Затем ОС выдаст вам void *, где файл отображается в памяти. Приведите это к символу [] и убедитесь, что в каждом потоке используются неперекрывающиеся подмассивы.

void foo(char* begin, char*end) { /* .... */ }
void* base_address = myOS_memory_map("example.binary");
myOS_start_thread(&foo, (char*)base_address, (char*)base_address + 1000);
myOS_start_thread(&foo, (char*)base_address+1000, (char*)base_address + 2000);
myOS_start_thread(&foo, (char*)base_address+2000, (char*)base_address + 3000);
4
ответ дан 3 December 2019 в 15:06
поделиться

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

Передача FILE_FLAG_OVERLAPPED в CreateFile () позволяет одновременное чтение и запись в один и тот же дескриптор файла; в противном случае Windows сериализует их.

2
ответ дан 3 December 2019 в 15:06
поделиться

Возможно, хотя я не уверен, что оно того стоит. Рассматривали ли вы чтение всего файла в память в одном потоке, а затем позволили нескольким потокам получить доступ к этим данным?

0
ответ дан 3 December 2019 в 15:06
поделиться

Чтение: нет необходимости блокировать файл. Просто откройте файл как доступный только для чтения или общий доступ для чтения.

Запись: используйте мьютекс, чтобы обеспечить запись в файл только одним человеком.

0
ответ дан 3 December 2019 в 15:06
поделиться

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

И как всегда при оптимизации, вы не должны пытаться делать это, пока у вас (1) не будет простого для понимания, работающего, решения, и (2) вы измерили свой код, чтобы узнать, где вы должны оптимизировать.

0
ответ дан 3 December 2019 в 15:06
поделиться

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

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

Что касается примера на C, вам нужно будет предоставить некоторую дополнительную информацию, как и используемая вами библиотека потоков. Сначала попробуйте, и мы поможем вам исправить любые проблемы.

2
ответ дан 3 December 2019 в 15:06
поделиться

Я не вижу в этом никакой реальной пользы.
У вас может быть несколько потоков чтения с устройства, но узким местом будет не ЦП, а скорость ввода-вывода диска.

Если вы не будете осторожны, вы можете даже замедлить процессы (но вам нужно будет измерить это, чтобы знать наверняка) .

2
ответ дан 3 December 2019 в 15:06
поделиться

You shouldn't need to do anything particularly clever if all they're doing is reading. Obviously you can read it as many times in parallel as you like, as long as you don't exclusively lock it. Writing is clearly another matter of course...

I do have to wonder why you'd want to though - it will likely perform badly since your HDD will waste a lot of time seeking back and forth rather than reading it all in one (relatively) uninterrupted sweep. For small files (like your 4000 line example) where that might not be such a problem, it doesn't seem worth the trouble.

0
ответ дан 3 December 2019 в 15:06
поделиться

Вам нужен способ синхронизации этих потоков. Существуют разные решения для мьютекса http://en.wikipedia.org/wiki/Mutual_exclusion

-1
ответ дан 3 December 2019 в 15:06
поделиться

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

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

-1
ответ дан 3 December 2019 в 15:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: