代码之家  ›  专栏  ›  技术社区  ›  doron

多线程堆管理

  •  11
  • doron  · 技术社区  · 16 年前

    在C/C++中,我可以在一个线程中分配内存,并在另一个线程中删除它。然而,每当从堆中请求内存时,堆分配器需要遍历堆以找到适当大小的空闲区域。两个线程如何在不损坏堆的情况下高效地访问同一堆?(这是通过锁定堆来完成的吗?)

    6 回复  |  直到 15 年前
        1
  •  9
  •   EmeryBerger    15 年前

    一般来说,您不需要担心内存分配器的线程安全性。所有标准的内存分配程序——也就是那些随MacOS、Windows、Linux等一起提供的程序——都是线程安全的。锁是提供线程安全性的标准方法,尽管可以编写只使用原子操作而不使用锁的内存分配器。

    现在,这些内存分配器是否 规模 ;也就是说,它们的性能是否独立于执行内存操作的线程数?在大多数情况下,答案是否定的;他们要么放慢速度,要么可以消费 很多 更多的记忆。在两个维度(速度和空间)中,第一个可伸缩的分配器是 Hoard (我写过);mac os x分配器受到它的启发——并在文档中引用它——但是囤积更快。还有其他一些,包括谷歌的tcmalloc。

        2
  •  3
  •   Community Mohan Dere    9 年前

    是的,支持多线程代码的“普通”堆实现必须包含某种锁,以确保正确的操作。在相当极端的条件下(a 许多 对于堆活动)这可能成为瓶颈;可以使用更专门的堆(通常提供某种线程本地堆),这有助于解决这种情况。我用过英特尔的TBB "scalable allocator" good effect . tcmalloc jemalloc 其他的malloc例子都是在考虑多线程伸缩的情况下实现的。

    单线程和多线程感知malloc的时序比较 here .

        3
  •  2
  •   doron    16 年前

    我发现 this 链接。

    基本上,堆可以分为竞技场。当请求内存时,将依次检查每个竞技场,以查看它是否被锁定。这意味着不同的线程可以同时安全地访问堆的不同部分。自由有点复杂,因为每个自由都必须从分配给它的竞技场中释放出来。我认为一个好的实现将使不同的线程默认为不同的竞技场,以尽量减少争用。

        4
  •  2
  •   T.E.D.    16 年前

    这是一个操作系统问题,所以答案将取决于操作系统。

    在窗户上,每个 过程 得到自己的堆。这意味着同一进程中的多个线程(默认情况下)共享一个堆。因此,操作系统必须对其分配和释放调用进行线程同步,以防止堆损坏。如果您不喜欢随后可能发生的争论,可以通过使用 Heap* routines . 你甚至可以重载MaloC(C)和新的(C++)来调用它们。

        5
  •  1
  •   GManNickG    16 年前

    是的,通常必须锁定对堆的访问。当您有一个共享资源时,需要保护该资源;内存是一个资源。

        6
  •  0
  •   Community Mohan Dere    9 年前

    这在很大程度上取决于您的平台/操作系统,但我相信这在主要系统上是可以的。C/C++不定义线程,所以默认情况下,我相信答案是“堆不受保护”,即必须为堆存取提供某种类型的多线程保护。

    但是,至少在Linux和GCC中,我相信启用-pthread将自动为您提供这种保护…

    此外,还有一个相关问题:

    C++ new operator thread safety in linux and gcc 4