windows - 从私有(private)堆分配内存会导致死锁吗?

标签 windows memory-management

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

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

如果必须增加私有(private)堆的大小会发生什么?必须再次存在某种全局锁来同步内存页到堆的分配。因此,根据我的理解,如果线程 2 在挂起期间持有此全局锁,仍然有可能导致死锁。这是正确的还是全局内存管理是通过某种特殊的“无锁原子”机制完成的?

编辑:

线程 2 可能会被 CLR 垃圾收集器或调用 SuspendThread 挂起。靠我自己。通过调用 HeapCreate 创建私有(private)堆.

最佳答案

正如 Hans Passant 和 David Heffernan 已经指出的那样,SuspendThread 对于众所周知的问题来说很麻烦,如果有人可以帮助它,那么永远就不会暂停线程,但让它阻塞在同步原语上。这样,您就可以提前知道何时可以阻塞、何时不能阻塞,并且这不会发生在内存分配过程中。

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

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

VirtualAlloc 或虚拟内存/内存映射子系统不能拥有“更大的锁”(嗯,它们当然,但不是由用户进程拥有的锁!)因为如果他们这样做,您将能够轻松地在计算机上运行拒绝服务攻击,从而使计算机上的所有其他进程陷入死锁。页面错误一直在发生,因此一旦计算机上的任何进程挂起线程,任何进程(即使是那些没有调用 VirtualAlloc 的进程)都不会是安全的。 幸运的是,事实并非如此(这将是一场噩梦!)。

到目前为止,您使用私有(private)堆的解决方案可能是一个不错的解决方案。

作为一种替代解决方案,由于您正在编写一个探查器并且需要为“统计”分配内存(CPU 使用、上下文切换、工作集大小,诸如此类的东西?),人们可能会认为这或多或少恒定的内存量,或至少具有可预测上限的内存量。
因此,您可以在挂起其他线程之前简单地分配内存。这意味着有关锁的任何问题并不重要。

关于windows - 从私有(private)堆分配内存会导致死锁吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21157044/

相关文章:

objective-c - 关于GNUstep AutoReleasePool的Objective-C未声明的问题

c - 为二维数组分配内存

php - 如何在 PHP 中安装 MySQL 模块?

linux - 在专用服务器上安装Windows Server

java - 如何通过多线程java编程最大化资源(RAM和CPU)使用率?

ios - 我应该如何存储一个大字符串,比如用户协议(protocol)?

c++ - 如何获取使用 malloc() 分配的内存块的大小?

windows - 批量检查两个文件的大小是否相同

windows - Window Server 上的 TeamSite 后备存储数据能否迁移到 Linux Server 上的 TeamSite?

windows - Windows 批处理中的 %%I 不管理带空格的名称