多个线程从同一个文件读取

我的平台是windows vista 32,带有visual c ++ express 2008。

例如:

如果我有一个包含4000个字节的文件,我可以同时从文件中读取4个线程吗? 并且每个线程访问文件的不同部分。

线程1读取0-999,线程2读取1000 – 2999等。

请用C语言举个例子。

如果你不写信给他们,则无需照顾同步/竞争条件。

只需打开共享阅读文件作为不同的句柄,一切都会工作。 (即,您必须在线程的上下文中打开文件,而不是共享相同的文件句柄)。

#include  #include  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; } 

诚然, 同一个文件甚至没有大问题。

到目前为止,最简单的方法是对文件进行内存映射。 然后操作系统会给你一个void *,文件被映射到内存中。 将其转换为char [],并确保每个线程使用非重叠的子数组。

 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); 

您当然可以从数据结构中读取多个线程,如果正在进行任何写入,则可能会出现竞争条件。

要避免这种竞争条件,您需要定义线程可以读取的边界,如果您有明确数量的数据段和明确数量的线程来匹配这些,那么这很容易。

至于C中的示例,您需要提供更多信息,例如您正在使用的线程库。 首先尝试,然后我们可以帮助您解决任何问题。

我认为这样做没有任何实际优势。
您可能有多个线程从设备读取,但您的瓶颈不是CPU而是磁盘IO速度。

如果你不小心,你甚至可能减慢进程(但你需要测量它以确定)。

Windows支持重叠I / O,允许单个线程异步排队多个I / O请求以获得更好的性能。 只要您访问的文件支持搜索(即这不是管道),这可以想象地被多个线程同时使用。

FILE_FLAG_OVERLAPPED传递给CreateFile()允许在同一文件句柄上同时进行读写操作; 否则,Windows序列化它们。 使用OVERLAPPED结构的OffsetOffsetHigh成员指定文件偏移量。

有关更多信息,请参阅同步和重叠输入和输出 。

最简单的方法是在每个并行实例中打开文件,但只需以只读方式打开它。

那些说可能存在IO瓶颈的人可能是错的。 任何现代操作系统都会缓存文件读取。 这意味着您第一次读取文件将是最慢的,任何后续读取将是闪电般快速。 4000字节的文件甚至可以放在处理器的缓存中。

如果他们所做的只是阅读,你不应该做任何特别聪明的事情。 显然,只要您不完全锁定它,您可以根据需要多次并行读取它。 写作显然是另一回事……

我不得不想知道你为什么要这么做 – 它可能会表现不好,因为你的硬盘会浪费很多时间来回寻找,而不是在一次(相对)不间断的扫描中读取它。 对于可能不是这样的问题的小文件(如4000行示例),它似乎不值得麻烦。

虽然我不确定它是否值得付出努力是可能的。 您是否考虑在单个线程中将整个文件读入内存,然后允许多个线程访问该数据?

阅读:无需锁定文件。 只需将文件作为只读或共享读取打开即可

写入:使用互斥锁确保文件仅由一个人写入。

正如其他人已经注意到的那样,只要具有自己的文件描述符/句柄,就可以从同一文件中读取多个线程。 但是,我对你的动机有点好奇。 为什么要读取并行文件? 如果您只是将文件读入内存,那么您的瓶颈可能就是磁盘本身,在这种情况下,multithreading根本不会帮助您(它只会使您的代码混乱)。

和往常一样,在优化之前,你不应该尝试它,直到你(1)有一个易于理解,工作,解决方案,(2)你已经测量了你的代码,知道你应该优化的位置。

 std::mutex mtx; void worker(int n) { mtx.lock(); char * memblock; ifstream file ("D:\\test.txt", ios::in); if (file.is_open()) { memblock = new char [1000]; file.seekg (n * 999, ios::beg); file.read (memblock, 999); memblock[999] = '\0'; cout << memblock << endl; file.close(); delete[] memblock; } else cout << "Unable to open file"; mtx.unlock(); } int main() { vector vec; for(int i=0; i < 3; i++) { vec.push_back(std::thread(&worker,i)); } std::for_each(vec.begin(), vec.end(), [](std::thread& th) { th.join(); }); return 0; } 

您需要一种方法来同步这些线程。 互斥体http://en.wikipedia.org/wiki/Mutual_exclusion有不同的解决方案

他想从不同的线程中读取文件 。 如果文件以每个线程的只读方式打开,我想这应该没问题。

我希望你不要为了性能而这样做,因为你必须扫描文件的大部分内容以获取每个线程中的换行符。