与 MemoryMappedFile 并行读写

Posted

技术标签:

【中文标题】与 MemoryMappedFile 并行读写【英文标题】:Reading and writing in parallel to MemoryMappedFile 【发布时间】:2015-07-30 14:23:32 【问题描述】:

如果我在同一个MemoryMappedFile 中并行读写会发生什么?是否有必要在阅读之前通过Mutext 锁定它们,如 MSDN 上的示例所示?

Memory-Mapped Files

【问题讨论】:

如何写入文件? 文件本身当然可以同时写入,单个访问器是"not guaranteed to be thread safe." 我想通过BinaryWriter从一个应用程序写入,并通过BinaryReader从另一个应用程序读取。 您是否尝试使用内存映射文件作为某种进程通信? 这绝对可以。我相信在示例中使用Mutex 只是为了同步演示流程的工作;否则,在写入者开始写入任何数据之前,读取过程可能已经终止。裸数据交换不需要同步,尽管您通常希望在数据准备好读取或写入时以某种方式发出信号。 【参考方案1】:

从内存映射文件创建的每个“视图”一次只能由一个线程访问,但是您可以创建多个视图流,并且每个线程可以同时对其进行写入或读取。

但是,如果多个视图尝试同时写入同一位置,您可能会得到相互“混合”的数据。示例中的互斥锁是为了防止这种混合。如果一个应用程序只写入文件而另一个应用程序只读取,则不需要互斥锁,您只需要多个写入器。

【讨论】:

这是需要的提示:`如果一个应用程序只写入文件而另一个应用程序只读取,则不需要互斥锁,您只需要多个写入器。` 谢谢!【参考方案2】:

简短的回答是,您可能会读取损坏的数据或写入损坏的数据,并且您必须获得独占访问权限(例如Mutex),除非读取和写入的时间安排得当(呃!)或者已知它们是'没有碰到内存映射文件的相同部分。

考虑在偏移量 100 处有 100 个字节长的数据块。一个写入器从偏移量 0 到 150 开始写入,另一个写入从 180 到 300。您的读取器在写入器写入时开始读取这 100 个字节。什么是阅读?如果另一位作家同时写 180 到 300 篇怎么办。写什么?很可能是一块交错的损坏数据。

解决这个问题的经典方法是使用读写锁。在 .NET 中,如果您在单个进程中进行并行读取和写入,则可以使用 ReaderWriterLockSlim 或更旧的 ReaderWriterLock

如果您想对多个进程执行此操作,您可以使用FileStream.Lock()FileStream.Unlock()。一个更棘手的解决方案是使用信号量和互斥体的组合。按照this SO question 的链接获取想法。

即使这样可能还不够。如果您的内存映射文件被您无法控制的进程(例如第三方)使用,那么您可能会受到损坏。上述解决方案是协作算法的示例(所有各方都知道发生了什么并采取相应的行动)。

最笨拙的方法是在使用FileShare.None 打开时锁定整个内存映射文件。

【讨论】:

以上是关于与 MemoryMappedFile 并行读写的主要内容,如果未能解决你的问题,请参考以下文章

C# MemoryMappedFile 会扩展吗?

.net 4.0 创建具有全局上下文的 MemoryMappedFile 会引发异常

MemoryMappedFile的初级应用

MemoryMappedFile 或序列化,超大对象的速度

并行程序没有速度增加与线性程序

线程同步之读写锁