线程是否有一个独特的堆?

据我所知,当线程由操作系统创build时,每个线程都得到一个独立的堆栈。 我不知道每个线程是否还有一个独特的堆栈?

不是。所有线程共享一个共同的堆。

每个线程都有一个私有堆栈 ,可以快速添加和删除项目。 这使基于堆栈的内存更快,但是如果使用太多的堆栈内存,就像在无限recursion中发生的那样,将会发生堆栈溢出。

由于所有线程共享相同的堆,因此必须同步对分配器/释放器的访问。 有各种避免分配器争用的方法和库。

有些语言允许您创build私有的内存池或单个堆,您可以将其分配给单个线程。

默认情况下,C只有一个堆。

也就是说,一些线程感知的分配器将对堆进行分区,以便每个线程都有自己的区域来分配。 这个想法是,这应该使堆规模更好。

囤积这样一个例子。

取决于操作系统。 Windows和unices上的标准c运行时使用跨线程的共享堆。 这意味着locking每个malloc / free。

例如,在Symbian上,每个线程都有自己的堆,尽pipe线程可以共享指向任何堆中分配的数据的指针。 Symbian的devise在我看来更好,因为它不但免除了在alloc / free期间locking的需要,而且还鼓励在线程之间清晰地指定数据所有权。 同样在这种情况下,当一个线程死亡时,它将所有与它一起分配的对象 – 即它不能泄漏它分配的对象,这是在具有受限内存的移动设备中具有的重要属性。

Erlang也遵循类似的devise,“stream程”作为垃圾收集的一个单元。 所有的数据通过复制在进程之间传递,除了引用计数的二进制blob(我认为)。

每个线程都有自己的堆栈和调用堆栈。

每个线程共享相同的堆。

这取决于你说“堆”时的意思。

所有线程共享地址空间,因此可以从所有线程访问堆分配的对象。 从技术上讲,堆栈也是共享的,即没有任何东西阻止你访问其他线程的堆栈(尽pipe这样做几乎没有任何意义)。

另一方面,有堆结构用于分配内存。 这是堆内存分配的所有记账完成的地方。 这些结构是精密组织的,以最大限度地减less线程之间的争用 – 所以一些线程可能共享堆结构(竞技场),有些可能会使用不同的舞台。
请参阅以下线程以获取有关详细信息的详细说明: malloc如何在multithreading环境中工作?

通常情况下,线程共享堆和其他资源,但是有类似线程的构造不会。 在这些类似线程的构造中,有Erlang的轻量级进程,以及UNIX的full-on进程(通过调用fork()来创build)。 您也可能正在处理多机并发,在这种情况下,您的线程间通信选项将受到更多的限制。

一般来说,所有线程使用相同的地址空间,因此通常只有一个堆。

但是,这可能会更复杂一些。 您可能正在寻找线程本地存储 (TLS),但它只存储单个值。

特定于Windows:可以使用TlsAlloc分配TLS空间,并使用TlsFree ( 此处概述)进行释放。 再一次,这不是一堆,只是DWORD。

奇怪的是,Windows支持每个进程多个堆 。 可以将堆的句柄存储在TLS中。 那么你会有一个像“线程本地堆”的东西。 然而,只有句柄不为其他线程所知,仍然可以使用指针访问它的内存,因为它仍然是相同的地址空间。

编辑 :一些内存分配器(特别是FreeBSD上的jemalloc )使用TLS将“ arenas ”分配给线程。 这样做是为了通过减less同步开销来优化多核的分配。

在FreeRTOS操作系统上,任务(线程)共享相同的堆,但每个堆都有自己的堆栈。 这在处理低功耗低RAM体系结构时非常方便,因为同一个内存池可以被多个线程访问/共享,但是这只是一个小小的捕获,开发人员需要记住的一个机制,用于同步malloc并且需要空闲,这就是为什么在分配或释放堆上的内存时(例如信号量或互斥锁)需要使用某种types的进程同步/locking的原因。