首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于在独立线程中并发地读取/写入同一文件的不同部分的多个FileStreams

用于在独立线程中并发地读取/写入同一文件的不同部分的多个FileStreams
EN

Stack Overflow用户
提问于 2012-06-23 12:04:51
回答 2查看 10.3K关注 0票数 5

我有一个大的磁盘文件(大约8GB),其中包含我需要读取、在内存中处理和写回另一个文件的数百万条记录。所有记录都是固定长度的(例如,100个字节)。

我正在考虑并行化我的进程以在多个线程(通常为4-8)上运行,每个线程都将(独占)分配给文件的一个特定部分来处理(例如,1 GB块)。由于每个线程都会限制其对已分配文件的部分的读和写,因此我的代码不存在发生种族冲突的风险。

是否允许我初始化多个线程(每个线程都有自己的FileStream ),以便在没有锁定的情况下读取/写入同一个文件,而不会导致损坏?假设目标文件已提前展开到其全部大小(使用FileStream.SetLength),并且在打开每个FileStream时指定了适当的FileShare标志。

此外,如果多个线程同时访问同一个文件,我是否会因为缓冲区的丢失而导致缓慢下降?我对FileStream class上的MSDN文档中的“检测流位置更改”部分表示关切,该部分指出:

FileStream对象对其句柄没有独占权时,另一个线程可以并发访问文件句柄,并更改与文件句柄关联的操作系统文件指针的位置。…

如果在对Read方法的调用中检测到句柄位置的意外更改,则.NET框架将丢弃缓冲区的内容并再次从文件中读取流。这可能会影响性能,这取决于文件的大小以及可能影响文件流位置的任何其他进程。

这是否适用于我的情况,或者FileStream实例创建的文件句柄是否是独立且独立的,即使访问同一个文件也是如此?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-06-23 12:25:04

这绝对安全。

MSDN文章中提到的问题没有风险,因为只有当您自己对底层句柄进行更改时,它才适用。您根本没有访问句柄。

不过,您会注意到随机磁盘IO会破坏性能。您可能希望通过从文件中读取大块(大约16 by )并使用锁来防止并发的读和写调用来减轻这一问题。请注意,即使在不同的FileStream实例上,您也需要防止并发调用,因为OS没有对IOs进行原子化处理。在内部,它们被分割成小尺寸,以保证公平性和可预测的延迟。这会导致随机IO。

为什么不创建一个阅读器线程将缓冲区推到BlockingCollection中呢?您可以在多个线程上使用Parallel.ForEach处理该集合。

票数 6
EN

Stack Overflow用户

发布于 2012-06-23 12:15:52

“内存映射文件将文件的内容映射到应用程序的逻辑地址空间。内存映射文件使程序员能够处理非常大的文件,因为内存可以并发管理,并且允许对文件进行完全、随机的访问,而不需要查找。内存映射的文件也可以跨多个进程共享。

CreateFromFile方法从指定的路径或磁盘上现有文件的FileStream创建内存映射文件。文件未映射时,更改将自动传播到磁盘。

CreateNew方法创建未映射到磁盘上现有文件的内存映射文件;并且适合为进程间通信(IPC)创建共享内存。

内存映射文件与名称相关联。

您可以创建内存映射文件的多个视图,包括文件部分的视图。您可以将文件的同一部分映射到多个地址以创建并发内存。要使两个视图保持并发状态,必须从同一个内存映射文件中创建它们。创建具有两个视图的同一个文件的两个文件映射并不提供并发性。“

http://msdn.microsoft.com/en-us/library/system.io.memorymappedfiles.memorymappedfile.aspx

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11169354

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档