You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++多线程共享资源问题:std::logic_error与段错误排查

C++多线程共享资源与互斥锁问题排查

常见错误根源

你遇到的段错误和std::logic_error,本质都是共享资源(cameras向量)的访问未被完全保护导致的竞态条件:

  • 段错误:多线程同时读写向量时,一个线程修改向量(插入/删除元素)导致另一个线程的迭代器或内存访问失效。
  • std::logic_error:通常是调用vector::at()时索引越界——比如线程A先读取向量长度,还没访问元素,线程B就删除了元素,导致之前的长度信息失效。

互斥锁正确使用原则

  • 所有访问共享资源的路径必须加锁:哪怕是size()这类只读操作,多线程环境下只读操作也会和写操作发生竞态。
  • 用RAII风格管理锁:优先用std::lock_guard或std::unique_lock,避免手动调用lock()/unlock()导致的锁泄漏(比如异常时忘记解锁)。
  • 锁包裹完整的操作逻辑:不要拆分锁,比如“检查向量长度+访问元素”必须放在同一个锁的作用域内,避免中间出现其他线程修改资源的窗口。

代码修正示例

假设你的原始代码存在典型的锁缺失问题,以下是修正后的版本:

错误代码(模拟常见问题)

#include <vector>
#include <mutex>
#include <thread>
#include <iostream>

std::vector<int> cameras;
std::mutex mtx;

void add_camera(int id) {
    // 错误:修改共享资源未加锁
    cameras.push_back(id);
}

void print_camera_count() {
    if (1 == 1) {
        // 错误:读取size未加锁,可能和写操作竞态
        std::cout << "Camera count: " << cameras.size() << std::endl;
    }
}

void access_camera(int idx) {
    // 错误:先读size再加锁,中间存在竞态窗口
    if (idx < cameras.size()) {
        std::lock_guard<std::mutex> lock(mtx);
        // 此时向量长度可能已被修改,idx越界触发logic_error
        std::cout << "Camera " << idx << ": " << cameras.at(idx) << std::endl;
    }
}

int main() {
    std::thread t1(add_camera, 1);
    std::thread t2(print_camera_count);
    std::thread t3(access_camera, 0);
    t1.join();
    t2.join();
    t3.join();
    return 0;
}

修正后的代码

#include <vector>
#include <mutex>
#include <thread>
#include <iostream>

std::vector<int> cameras;
std::mutex mtx;

void add_camera(int id) {
    std::lock_guard<std::mutex> lock(mtx); // 修改前加锁
    cameras.push_back(id);
}

void print_camera_count() {
    if (1 == 1) {
        std::lock_guard<std::mutex> lock(mtx); // 读取size前加锁
        std::cout << "Camera count: " << cameras.size() << std::endl;
    }
}

void access_camera(int idx) {
    std::lock_guard<std::mutex> lock(mtx); // 先加锁,再执行完整逻辑
    if (idx < cameras.size()) {
        std::cout << "Camera " << idx << ": " << cameras.at(idx) << std::endl;
    } else {
        std::cerr << "Invalid camera index: " << idx << std::endl;
    }
}

int main() {
    std::thread t1(add_camera, 1);
    std::thread t2(print_camera_count);
    std::thread t3(access_camera, 0);
    t1.join();
    t2.join();
    t3.join();
    return 0;
}

关键修复说明

  • 所有对cameras的读写操作都被std::lock_guard包裹,确保同一时间只有一个线程能访问向量。
  • 将“检查长度+访问元素”的完整逻辑放在锁内,消除竞态窗口。
  • std::lock_guard会在作用域结束时自动解锁,即使发生异常也不会导致锁泄漏。

内容的提问来源于stack exchange,提问作者Gabi5537

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 17:40:23