每个程序员很快就会了解多线程的一条规则是:
如果多个线程可以访问一个数据结构,并且至少有一个线程可能会修改该数据结构,那么您最好序列化对该数据结构的所有访问,否则您将面临调试痛苦的世界。
通常,这种序列化是通过互斥锁完成的——即,想要读取或写入数据结构的线程会锁定互斥锁,做它需要做的任何事情,然后解锁互斥锁以使其再次可供其他线程使用。
这让我明白了这一点:进程的内存堆是一个可由多个线程访问的数据结构。这是否意味着对默认/非重载 new
和 delete
的每次调用都由进程全局互斥体序列化,因此是可能减慢速度的潜在序列化瓶颈多线程程序?或者现代堆实现是否以某种方式避免或缓解了这个问题,如果是,他们是如何做到的?
(注意:我标记了这个问题 linux
,以避免正确但不具信息性的“它依赖于实现”的响应,但我也有兴趣了解 Windows 和如果实现之间存在显着差异,MacOS/X 也会这样做)
最佳答案
new
和 delete
是 thread safe
The following functions are required to be thread-safe:
- The library versions of
operator new
andoperator delete
- User replacement versions of global
operator new
andoperator delete
std::calloc
,std::malloc
,std::realloc
,std::aligned_alloc
,std::free
Calls to these functions that allocate or deallocate a particular unit of storage occur in a single total order, and each such deallocation call happens-before the next allocation (if any) in this order.
使用 gcc,new
是通过委托(delegate)给 malloc
来实现的,我们看到他们的 malloc
确实是 use a lock .如果您担心分配会导致瓶颈,请编写自己的分配器。
关于c++ - 对堆的访问是否序列化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56196399/