Linux malloc 在多线程环境中是如何工作的?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10706466/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 06:26:10  来源:igfitidea点击:

How does malloc work in a multithreaded environment?

clinuxgccmallocx86-64

提问by pythonic

Does the typical malloc(for x86-64 platform and Linux OS) naively lock a mutex at the beginning and release it when done, or does it lock a mutex in a more clever way at a finer level, so that lock contention is reduced? If it indeed does it the second way, how does it do it?

典型的malloc(对于 x86-64 平台和 Linux 操作系统)是在开始时天真地锁定互斥锁并在完成时释放它,还是在更精细的级别以更聪明的方式锁定互斥锁,从而减少锁争用?如果它确实采用第二种方式,它是如何做到的?

采纳答案by NPE

glibc 2.15operates multiple allocation arenas. Each arena has its own lock. When a thread needs to allocate memory, malloc()picks an arena, locks it, and allocates memory from it.

glibc 2.15经营多个分配领域。每个竞技场都有自己的锁。当一个线程需要分配内存时,malloc()选择一个arena,锁定它,并从中分配内存。

The mechanism for choosing an arena is somewhat elaborate and is aimed at reducing lock contention:

选择 arena 的机制有些复杂,旨在减少锁争用:

/* arena_get() acquires an arena and locks the corresponding mutex.
   First, try the one last locked successfully by this thread.  (This
   is the common case and handled with a macro for speed.)  Then, loop
   once over the circularly linked list of arenas.  If no arena is
   readily available, create a new one.  In this latter case, `size'
   is just a hint as to how much memory will be required immediately
   in the new arena. */

With this in mind, malloc()basically looks like this (edited for brevity):

考虑到这一点,malloc()基本上看起来像这样(为简洁起见进行了编辑):

  mstate ar_ptr;
  void *victim;

  arena_lookup(ar_ptr);
  arena_lock(ar_ptr, bytes);
  if(!ar_ptr)
    return 0;
  victim = _int_malloc(ar_ptr, bytes);
  if(!victim) {
    /* Maybe the failure is due to running out of mmapped areas. */
    if(ar_ptr != &main_arena) {
      (void)mutex_unlock(&ar_ptr->mutex);
      ar_ptr = &main_arena;
      (void)mutex_lock(&ar_ptr->mutex);
      victim = _int_malloc(ar_ptr, bytes);
      (void)mutex_unlock(&ar_ptr->mutex);
    } else {
      /* ... or sbrk() has failed and there is still a chance to mmap() */
      ar_ptr = arena_get2(ar_ptr->next ? ar_ptr : 0, bytes);
      (void)mutex_unlock(&main_arena.mutex);
      if(ar_ptr) {
        victim = _int_malloc(ar_ptr, bytes);
        (void)mutex_unlock(&ar_ptr->mutex);
      }
    }
  } else
    (void)mutex_unlock(&ar_ptr->mutex);

  return victim;

This allocator is called ptmalloc. It is based on earlier workby Doug Lea, and is maintained by Wolfram Gloger.

这个分配器被称为ptmalloc. 它基于Doug Lea 的早期工作,由 Wolfram Gloger 维护。

回答by Adam Rosenfield

Doug Lea's mallocused coarse locking (or no locking, depending on the configuration settings), where every call to malloc/realloc/freeis protected by a global mutex. This is safe but can be inefficient in highly multithreaded environments.

Doug Lea的malloc使用粗锁(或无锁定,这取决于配置设置),在每次调用malloc/ realloc/free是一个全球性的互斥体的保护。这是安全的,但在高度多线程的环境中可能效率低下。

ptmalloc3, which is the default mallocimplementation in the GNU C library (libc) used on most Linux systems these days, has a more fine-grained strategy, as described in aix's answer, which allows multiple threads to concurrently allocate memory safely.

ptmalloc3是当今malloc大多数 Linux 系统上使用的 GNU C 库 (libc) 中的默认实现,它具有更细粒度的策略,如aix 的回答中所述,它允许多个线程安全地并发分配内存。

nedmallocis another independent implementation which claims even better multithreaded performance than ptmalloc3and various other allocators. I don't know how it works, and there doesn't seem to be any obvious documentation, so you'll have to check the source code to see how it works.

nedmalloc是另一个独立的实现,它声称比ptmalloc3其他各种分配器具有更好的多线程性能。我不知道它是如何工作的,而且似乎没有任何明显的文档,因此您必须检查源代码以了解它是如何工作的。