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
How does malloc work in a multithreaded environment?
提问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.15
operates 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.
回答by Adam Rosenfield
Doug Lea's malloc
used coarse locking (or no locking, depending on the configuration settings), where every call to malloc
/realloc
/free
is 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 malloc
implementation 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 的回答中所述,它允许多个线程安全地并发分配内存。
nedmalloc
is another independent implementation which claims even better multithreaded performance than ptmalloc3
and 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
其他各种分配器具有更好的多线程性能。我不知道它是如何工作的,而且似乎没有任何明显的文档,因此您必须检查源代码以了解它是如何工作的。