我的平台是windows vista 32,带有visual c ++ express 2008。
例如:
如果我有一个包含4000个字节的文件,我可以同时从文件中读取4个线程吗?每个线程访问文件的不同部分。
线程1读取0-999,线程2读取1000 - 2999等
请用C语言举例。
答案 0 :(得分:21)
如果您不写信给他们,则无需处理同步/竞争状况。
只需打开带有共享阅读的文件作为不同的句柄,一切都会起作用。 (即,您必须在线程的上下文中打开文件,而不是共享相同的文件句柄。)
#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;
}
答案 1 :(得分:4)
诚实地,写甚至没有一个大问题。
到目前为止,最简单的方法是对文件进行内存映射。操作系统将为您提供一个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);
答案 2 :(得分:2)
您当然可以从数据结构中读取多个线程,如果正在进行任何编写,则可能会出现竞争条件。
要避免这种竞争条件,您需要定义线程可以读取的边界,如果您有明确数量的数据段和明确数量的线程来匹配这些,那么这很容易。
至于C中的示例,您需要提供更多信息,例如您正在使用的线程库。首先尝试,然后我们可以帮助您解决任何问题。
答案 3 :(得分:2)
我认为这样做没有任何实际优势 您可能有多个线程从设备读取,但您的瓶颈不是CPU,而是磁盘IO速度。
如果你不小心,你甚至可能会减慢进程的速度(但你需要对其进行测量才能确定)。
答案 4 :(得分:2)
Windows支持重叠I / O,允许单个线程异步排队多个I / O请求以获得更好的性能。只要您访问的文件支持搜索(即这不是管道),这可以被多个线程同时使用。
将FILE_FLAG_OVERLAPPED
传递给CreateFile()
允许在同一文件句柄上同时进行读写操作;否则,Windows序列化它们。使用OVERLAPPED
结构的Offset
和OffsetHigh
成员指定文件偏移量。
答案 5 :(得分:1)
最简单的方法是在每个并行实例中打开文件,但只需将其打开即可。
那些认为可能存在IO瓶颈的人可能是错的。任何现代操作系统都会缓存文件读取。这意味着第一次读取文件时速度最慢,任何后续读取都会很快。一个4000字节的文件甚至可以放在处理器的缓存中。
答案 6 :(得分:0)
如果他们所做的只是阅读,你不应该做任何特别聪明的事情。显然,只要您不完全锁定它,您可以根据需要多次并行读取它。写作显然是另一回事......
我不得不想知道你为什么要这样做 - 它可能会表现不佳,因为你的硬盘将浪费大量时间来回寻找,而不是在一次(相对)不间断的扫描中阅读。对于可能不是这样的问题的小文件(例如你的4000行示例),它似乎不值得麻烦。
答案 7 :(得分:0)
虽然我不确定它是否值得付出努力。您是否考虑在单个线程中将整个文件读入内存,然后允许多个线程访问该数据?
答案 8 :(得分:0)
阅读:无需锁定文件。只需将文件打开为只读或共享读取
即可写入:使用互斥锁确保文件仅由一个人写入。
答案 9 :(得分:0)
正如其他人已经注意到的那样,只要拥有自己的文件描述符/句柄,就可以从同一个文件中读取多个线程。但是,我对你的动机有点好奇。为什么要读取并行文件?如果您只是将文件读入内存,那么您的瓶颈可能就是磁盘本身,在这种情况下,多个线程根本不会帮助您(它只会使您的代码混乱)。
与优化时一样,在您(1)有一个易于理解,有效的解决方案,以及(2)您已经测量了代码以了解应该优化的位置之前,您不应该尝试它。
答案 10 :(得分:0)
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<std::thread> 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;
}
答案 11 :(得分:-1)
您需要一种方法来同步这些线程。互斥锁http://en.wikipedia.org/wiki/Mutual_exclusion
有不同的解决方案答案 12 :(得分:-1)
他想在不同的帖子中读取文件。如果文件以每个线程的只读方式打开,我想这应该没问题。
我希望你不要为性能而这样做,因为你必须扫描文件的大部分内容以获取每个线程中的换行符。