Threadsafe内存管理器:320 MB缓冲区中的数据竞争?

时间:2013-02-19 11:13:42

标签: multithreading visual-c++ memory-management thread-safety

我正在研究一个多线程VC ++(windows)程序,它在主线程中执行一些连续模拟。此模拟使用在同一个线程或加载器线程中创建的对象(两者都可以是这种情况)。删除也是如此。

我做了这个,所以主线程不会阻塞,而非常大的对象(由很多的其他对象组成)被动态加载和卸载。这基本上有效。但是(例如)当卸载器线程连续删除一个对象时,其他线程的新调用和删除调用将永远消失。这似乎是由一些内部线程保护引起的。

我的下一步行动是通过汇集那些许多较小的对象来减少新/删除呼叫的数量。所以我写了一个原始的内存管理器。管理器使用malloc()分配320 MB缓冲区,并使用64字节的块为程序的其他部分提供分配功能。现在我使用placement new来创建较小的对象。经理的alloc / free方法完全是互斥(锁定)保护。

现在发生的事情是它在多线程环境中无法正常工作。自定义托管对象的修改将被忽略,依此类推。我假设发生的事情是整个缓冲区被视为单个变量,因此不能有读/写数据竞争。是这种情况吗?

在创建/删除完全不同的对象时限制对一个对象的访问不是您可以想象的选项。那么这样的情况会怎样?

2 个答案:

答案 0 :(得分:2)

newdelete在内部同步到单个Windows堆对象上。

我所知道的最佳解决方案是直接使用HeapCreate HeapAllocHeapFree,每个分配器线程创建一个堆对象,每次都指定HEAP_NO_SERIALIZE。

你必须确保分配的线程是释放的线程,即你必须“将内存返回”分配给辅助线程。

答案 1 :(得分:0)

  

是这样的吗?

不,我不这么认为。所有内存只是一个连续的地址空间。 CPU不知道变量,它只操作页面,缓存行和字节。

可能的原因:内存管理器中的错误。也许它分配的对象相互重叠,或者你的线程同步失败了(顺便说一下,你绝对应该用关键部分替换你的互斥体,参见CComAutoCriticalSection和CComCritSecLock ATL类以方便whappers - 对于简短的操作,它们的工作速度提高了一个数量级而不是互斥体。)

可能的原因:对象中的错误。也许你的对象在其地址之后写了一个额外的字节,但是堆舍入了分配大小,所以当每个对象都被新运算符使用的HeapAlloc win32 API分配时,它可以正常工作。

可能的原因:内存对齐问题。尝试将您分配的对象的地址至少对齐为8。