在内存映射文件中同时进行读写操作

3
如果我在同一个MemoryMappedFile中同时读写,会发生什么?是否有必要像MSDN示例中所示,在读取之前通过Mutext进行锁定? 内存映射文件

你如何写入文件?当然,文件本身可以同时被写入,但单个访问器“不能保证线程安全”。(https://msdn.microsoft.com/zh-cn/library/system.io.memorymappedfiles.memorymappedviewaccessor(v=vs.110).aspx) - JimmyB
我想通过BinaryWriter从一个应用程序写入数据,然后通过BinaryReader从另一个应用程序读取数据。 - BendEg
你是在尝试使用内存映射文件作为某种进程通信吗? - Ron Beyer
这肯定会起作用。我相信示例中使用Mutex仅是为了同步演示进程的工作;否则,在写入任何数据之前,读取进程可能已经终止。裸数据交换不需要同步,尽管通常希望在数据准备好被读取或写入时发出某种信号。 - JimmyB
2个回答

6

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

然而,如果多个视图尝试同时写入相同的位置,则可能会使数据“混合”在一起。示例中的互斥锁可防止此类混合。如果一个应用程序仅写入文件,而另一个应用程序仅读取,则不需要互斥锁,只有多个写入者才需要它。


这是需要的提示:如果一个应用程序仅写入文件,而另一个应用程序仅读取文件,则不需要互斥量,您只需要为多个编写者使用它。谢谢! - BendEg

1
简短的回答是,如果读写不是在同一内存映射文件的相同部分进行,或者读写时间很好地协调,那么您可能会读取到损坏的数据或写入损坏的数据,并且必须获得独占访问(例如使用Mutex)。
考虑一个偏移量为100且长度为100字节的数据块。一个写入者从偏移量0开始写入到150,另一个写入者从180写入到300。当写入者正在写入时,您的读取器开始读取这100个字节。读取到什么?如果另一个写入者同时从180写入到300,会写入什么?很可能是交错的损坏数据块。
解决此问题的经典方法是使用读写锁。在.NET中,如果您在单个进程中进行并行读写,则可以使用ReaderWriterLockSlim或较旧的ReaderWriterLock
如果您想使用多个进程来完成此操作,可以使用 FileStream.Lock()FileStream.Unlock()。更棘手的解决方案是同时使用信号量和互斥锁。查看 this SO question 中的链接以获取更多思路。
即使如此,这也可能不足够。如果您无法控制使用内存映射文件的进程(例如第三方进程),则可能会出现损坏。上述解决方案是合作算法的示例(所有参与方都知道发生了什么并相应地行事)。
最严厉的方法是在打开时使用 FileShare.None 锁定整个内存映射文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接