Answers:
否。所有线程共享一个公共堆。
每个线程都有一个专用堆栈,它可以快速添加和删除其中的项目。这样可以使基于堆栈的内存速度更快,但是如果您使用过多的堆栈内存(如无限递归中的情况),则会出现堆栈溢出。
由于所有线程共享同一个堆,因此必须同步对分配器/取消分配器的访问。有很多避免分配器争用的方法和库。
某些语言允许您创建专用的内存池或单个堆,您可以将其分配给单个线程。
you will get a stack overflow.
堆栈溢出导致堆栈溢出!
取决于操作系统。Windows和unices上的标准c运行时在线程之间使用共享堆。这意味着锁定每个malloc / free。
例如,在Symbian上,每个线程都有自己的堆,尽管线程可以共享指向任何堆中分配的数据的指针。在我看来,Symbian的设计更好,因为它不仅消除了在alloc / free期间锁定的需求,而且鼓励对线程之间的数据所有权进行明确的规范。同样在这种情况下,当线程死亡时,它会带走它所分配的所有对象-即它不能泄漏已分配的对象,这是在内存受限的移动设备中拥有的重要属性。
Erlang也遵循类似的设计,其中“进程”充当垃圾收集的单元。除了二进制引用引用计数的二进制Blob(我认为)外,所有数据都通过复制在进程之间进行通信。
这取决于您说“堆”时的确切含义。
所有线程共享地址空间,因此可以从所有线程访问分配堆的对象。从技术上讲,堆栈在这种意义上也是共享的,即没有什么可以阻止您访问其他线程的堆栈(尽管这样做几乎是没有任何意义的)。
另一方面,存在用于分配内存的堆结构。在那里完成了所有用于堆内存分配的簿记工作。这些结构经过精心组织,以最大程度地减少线程之间的争用-因此某些线程可能共享堆结构(一个竞技场),而某些线程可能使用不同的竞技场。
有关详细信息,请参见以下线程:malloc如何在多线程环境中工作?
通常,线程共享堆和其他资源,但是有类似线程的结构却没有。在这些类似线程的构造中,有Erlang的轻量级进程和UNIX的完整进程(通过调用来创建fork()
)。您可能还正在处理多计算机并发,在这种情况下,线程间通信选项将受到更大的限制。
一般而言,所有线程都使用相同的地址空间,因此通常只有一个堆。
但是,它可能会更复杂。您可能正在寻找线程本地存储(TLS),但它仅存储单个值。
Windows特定:TLS空间可以使用TlsAlloc分配,并可以使用TlsFree释放(在此处概述)。同样,它不是堆,而只是DWORD。
奇怪的是,Windows 每个进程支持多个堆。可以将堆的句柄存储在TLS中。然后,您将获得类似“线程本地堆”的信息。但是,只是其他线程不知道该句柄,它们仍然可以使用指针访问其内存,因为它仍然是相同的地址空间。
编辑:某些内存分配器(特别是FreeBSD上的jemalloc)使用TLS来为线程分配“竞技场”。这样做是通过减少同步开销来优化多个内核的分配。