多线程下无锁调用std::list::back()是否会引发core dump?
无锁调用list.back()是否会引发Core Dump?
假设有大量线程,每个线程执行以下三种操作之一:
auto a = list.back(); // 无互斥锁保护 list.pop_back(); // 有互斥锁保护,保证列表非空 list.push_front(); // 有互斥锁保护
已知操作1会得到不可预测的值,请问该操作是否会引发core dump?
补充信息:列表元素为包含shared_ptr和整数的结构体,我仅需获取整数值,可接受偶尔的异常值,但绝对不希望出现core dump。我尝试先调用list.back()再执行pop_back(),以及在列表为空时调用list.back(),均未触发core dump。
这种情况确实存在触发Core Dump的风险,具体原因如下:
- 当其他线程在你调用
list.back()的同时执行pop_back()时,back()返回的引用可能指向已经被销毁的内存区域。虽然你只读取其中的整数值,但如果结构体的内存已经被释放(比如pop_back()销毁最后一个元素后,内存被系统回收或被其他操作复用),此时访问这块内存就可能触发段错误,直接导致Core Dump。 - 你之前的测试没触发崩溃不代表没有风险:测试场景的线程调度时机、内存分配策略都可能让非法内存访问暂时没表现出崩溃,但在高并发或特定环境下(比如内存紧张时),这种风险很容易转化为实际的Core Dump。
- 另外,即使是读取整数,若
list的内部节点结构在并发操作中被破坏(比如push_front()或pop_back()修改链表尾指针的同时,back()正好在读取尾指针),也可能导致back()返回无效指针,进而引发非法内存访问。
如果要完全规避Core Dump风险,最稳妥的方式是给list.back()也加上互斥锁保护,或者改用线程安全的容器。如果实在不想加锁,至少要尽量缩小竞态窗口——比如先用锁保护检查列表非空,然后拷贝元素(而非直接取引用),但这种方式仍不能彻底消除风险。
内容的提问来源于stack exchange,提问作者LightCone
相关产品推荐
相关产品推荐

