std::shared_ptr赋值是否为原子操作?多线程并发赋值行为分析
1. std::shared_ptr的赋值操作是否为原子操作?
不是。std::shared_ptr的普通赋值运算符(operator=)不属于原子操作。C++标准仅规定了针对std::shared_ptr的专门原子操作函数(如std::atomic_store、std::atomic_load、std::atomic_exchange等特化版本)才具备原子性。
普通赋值过程包含两个关键步骤:更新内部指针指向、修改引用计数,这两步无法保证原子执行。多线程直接对同一个std::shared_ptr执行普通赋值,会引发数据竞争,属于未定义行为。
2. 多线程对同一shared_ptr赋值时,线程会等待对方完成完整赋值吗?
先指出你提供的代码存在问题:lambda表达式中使用[=s1]是按值捕获了s1的副本,线程内部修改的是各自的副本,而非全局的s1。若要修改同一个s1,需要改为引用捕获[&s1]。
假设修正为引用捕获后,核心结论是:t2不会等待t1的完整赋值操作完成,具体细节如下:
std::make_shared<int>(2)的内存分配和对象构造是在赋值给s1之前完成的,这部分操作是线程各自独立执行的,t1的内存分配阶段和t2的内存分配阶段完全并行,互不干扰。- 当执行
s1 = ...的赋值操作时,由于普通赋值不是原子操作,t1和t2的赋值步骤会交叉执行,引发数据竞争。这种情况下可能出现多种错误结果:比如引用计数被错误增减导致内存泄漏或二次释放,或者s1最终的指针指向混乱,既不是t1赋值的对象也不是t2赋值的对象。
如果需要多线程安全地修改std::shared_ptr,必须使用标准库提供的原子操作函数,而非普通赋值。
内容的提问来源于stack exchange,提问作者Daniel Aviv
相关产品推荐
相关产品推荐

