从私有堆分配内存会导致死锁?

我有两个线程。 线程1定期挂起线程2以收集一些统计信息。 线程1需要为这些统计分配内存,而另一个线程被挂起。 由于挂起的线程可能会持有堆锁,因此如果内存是由线程1从同一堆分配的,则可能会发生死锁。

可能的解决方案:为线程1使用私有堆以避免死锁。

如果必须增加私有堆的大小会发生什么? 必须再次出现某种全局锁,将内存页面的分配与堆分配同步。 因此,根据我的理解,如果线程2在暂停期间持有此全局锁定,则仍有可能导致死锁。 这是正确的还是用一些特殊的“无锁原子”机制完成全局内存管理?

编辑:

线程2可能会被CLR垃圾回收器暂停或通过我自己的方式调用SuspendThread。 通过调用HeapCreate创建一个私有堆。


正如Hans Passant和David Heffernan已经指出的那样, SuspendThread对于众所周知的问题是很麻烦的,如果有人可以帮助它,那么永远不会挂起一个线程,而是让它阻塞在一个同步原语上。 这样,你就可以提前知道它何时可以及何时不能阻塞,并且这不会在内存分配的中间。

显然这对于​​你的应用来说不太可能。

它指定每个堆都受到来自多线程访问的单个锁的保护。 因此,使用您所设想的私人堆听起来像是一个可行的解决方案。 HeapCreate保留指定最大大小的地址空间并为初始大小提交内存。 之后它并不真正“增长”,而只是在已经保留的地址空间中提交了更多的内存。
虽然没有指定堆的确切操作(所以我们只能猜测),但这不是应该能够死锁的东西,因为它可能仅仅是对VirtualAlloc调用(或者取决于如何实现它,它可能只是保护页面上的pagefault,例如堆栈以这种方式提交它的内存)。

VirtualAlloc或虚拟内存/内存映射子系统不能拥有“更大的锁定”(当然,他们当然会这样做,但不是用户进程拥有的),因为如果他们这样做了,你可以轻松地运行拒绝服务攻击在计算机上,会使计算机上的其他进程发生死锁。 页面错误一直在发生,因此一旦计算机上的任何进程暂停了一个线程,就没有进程(即使那些不调用VirtualAlloc进程)也是安全的。 幸运的是,情况并非如此(这将是一场噩梦!)。

就目前而言,使用私有堆的解决方案可能是一个很好的解决方案。

作为一种替代解决方案,因为您正在编写一个分析器,并且需要为“统计”(CPU使用,上下文切换,工作集大小,类似的东西?)分配内存,可以假设这或多或少是一个常量的内存,或至少一个具有可预测上限的数量。
因此,您可以暂停其他线程之前简单地分配内存。 这意味着有关锁的任何问题都无关紧要。


你的假设条件如下:

  • 线程2拥有一个锁。
  • 线程2暂停。
  • 线程1尝试获取锁。
  • 线程2将只被线程1恢复。
  • 当所有这些条件成立时,你就陷入僵局。

    链接地址: http://www.djcxy.com/p/31609.html

    上一篇: Can allocating memory from a private heap cause a deadlock?

    下一篇: stack allocated memory versus dynamically allocated memory