synchronized_pool_resource在多线程下更慢是因为其线程安全依赖全局粗粒度互斥锁,导致高频分配时严重锁竞争;适合低频调用或跨线程只读传递内存,而非高并发分配场景。

它不是“开箱即用的线程安全加速器”,而是需要你主动隔离使用场景的锁保护资源。直接在多线程高频分配小对象(比如 int、std::string)时共享一个 std::pmr::synchronized_pool_resource 实例,大概率比默认 new 还慢——因为所有线程争抢同一把全局互斥锁。
为什么 synchronized_pool_resource 在多线程下反而更慢?
它的线程安全是靠内部一把粗粒度互斥锁实现的,不是按块大小分片或按线程局部缓存。只要两个线程同时调用 allocate() 或 deallocate(),就会串行等待。
- 实测中,在 8 线程、每秒百万级
int分配场景下,吞吐量常比单线程还低 3–5 倍 - 锁竞争热点集中在
do_allocate和do_deallocate的入口处,perf profile 显示 70%+ 时间花在 futex_wait - 它适合的场景其实是:低频调用(如配置加载期一次性建几百个对象)、或跨线程传递已分配内存(比如主线程池分配,子线程只读不释放)
怎么正确使用 synchronized_pool_resource?
核心原则是:**别让它成为并发瓶颈,而要让它承担“安全交接”的职责**。
- 仅在真正需要跨线程共享并释放内存时才用它,例如:一个线程分配对象,另一个线程负责销毁(且销毁频率很低)
- 构造时显式传入上游资源(如
std::pmr::new_delete_resource()),避免依赖全局默认资源,方便调试和替换:std::pmr::synchronized_pool_resource pool{std::pmr::new_delete_resource()}; - 若需高性能并发分配,改用
std::pmr::unsynchronized_pool_resource+ 线程局部存储(TLS):每个线程持有一个独立池实例,完全无锁 - 不要把它塞进长期运行的循环里反复 allocate/deallocate;更适合一次性批量初始化 + 后续只读访问
常见误用:容器生命周期与资源生命周期不匹配
std::pmr::vector 本身不管理资源生命周期,它只持有一个 std::pmr::memory_resource* 指针。如果资源对象提前析构,后续容器操作(如 push_back)会 crash。
立即学习“C++免费学习笔记(深入)”;
- 错误写法:
{ std::pmr::synchronized_pool_resource pool; std::pmr::vector<int> v{&pool}; // pool 离开作用域后 v 变成悬挂指针 } - 正确做法:确保资源对象的生存期严格长于所有使用它的容器,通常放在类成员或静态/全局作用域
- 调试技巧:重载
allocate()方法,在返回前加断言assert(ptr != nullptr),避免静默空指针导致后续解引用崩溃
真正难的从来不是“怎么调用这个类”,而是判断“此刻该不该用它”。synchronized_pool_resource 的价值不在性能,而在语义——它明确告诉你:这块内存可以被多个线程安全地归还。其余部分,得靠你设计好分配节奏和生命周期边界。


















