正如内存映射文件的名称所示,我知道可以使用C#中的类MemoryMappedFile
将大文件的一部分映射到内存以进行快速数据处理。我想对内存映射文件做的是并行处理映射的内存。为了做到这一点,我有以下问题
MemoryMappedFileViewAccessor
线程安全且Parallel.For-safe?我实际上制作了一个演示程序来测试这个问题,它似乎正在起作用。但是找不到任何关于此的参考。如果答案是肯定的,我就完成了。否则,MemoryMappedFileViewAccessor
有ReadArray方法,但使用该方法是重复内存。答案 0 :(得分:10)
你可以说明这一点。内存映射文件只是程序中的一块内存,其字节可由多个进程访问。它们在托管代码中非常笨拙,因为这个块存在于特定地址。这需要使用指针访问数据,它们在托管代码中是禁忌。 MemoryMappedFileViewAccessor包装该指针,它将将数据从托管内存复制到共享内存。请注意,这会破坏使用MMF的主要原因,以及为什么他们的支持需要花费很长时间才能显示在.NET中。请确保您不想使用命名管道。
因此推断出这一点,MMF肯定不是设计上的线程安全的,因为这是共享内存,就像代码中的全局变量一样。如果线程读取和写入共享内存的相同部分,则完全相同的方式出错。并且你必须保护完全相同,锁定以确保只有一个线程可以访问共享部分。
另请注意,您需要在读取和写入MMF的进程之间实现该锁定。这往往是痛苦的,您必须使用“主”进程创建的命名互斥锁,并打开“从属”进程。你不能吝啬锁定要求。值得注意的是,你从未在你的问题中提到过这样做,所以那里有红旗。
在一个进程中,不访问MMF的同一部分的线程不能相互进入。就像两个访问不同变量的线程一样,不需要任何同步。只要他们持有互斥锁,确保另一个进程无法写入该部分。请注意,这可能意味着您希望使用信号量来保护MMF访问,只能通过一个线程获取互斥锁。
答案 1 :(得分:3)
在内部,MemoryMappedViewAccessor派生自UnmanagedMemoryAccessor,它看起来是不可变的,虽然没有只读字段 - 至少它不会在读/写操作期间修改现有字段,这使得它是线程安全的。反过来,它从SafeBuffer类读取内存映射文件数据,其中包含comments header中的以下文本:
/* Keep the penalties for using this class small, both in terms of space
// and time. Having multiple threads reading from a memory mapped file
// will already require 2 additional interlocked operations. If we add in
// a "current position" concept, that requires additional space in memory and
// synchronization. Since the position in memory is often (but not always)
// something that can be stored on the stack, we can save some memory by
// excluding it from this object. However, avoiding the need for
// synchronization is a more significant win. This design allows multiple
// threads to read and write memory simultaneously without locks (as long as
// you don't write to a region of memory that overlaps with what another
// thread is accessing).
所以我的猜测是内存映射文件的操作是线程安全的,尽管奇怪的是在MSDN中没有确认这一点。
答案 2 :(得分:0)
1)MSDN声明MemoryMappedFile
和MemoryMappedViewAccessor
:
此类型的任何公共静态(在Visual Basic中为Shared)成员都是线程安全的。不保证任何实例成员都是线程安全的。
2)MemoryMappedFile的重点不是减少内存分配。如果您从磁盘读取文件,则必须分配内存来存储从文件中读取的项目。内存映射文件也是如此