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

两线程同步问题:消除C26110警告及无手动Mutex实现

线程同步问题:Pipeline初始化完成后创建Connection

问题1:C26110警告的含义

C26110是微软静态代码分析工具抛出的警告,核心含义是:当前线程在调用std::_Mutex_base::unlock时,并没有持有该mutex的锁。

看你的代码逻辑:

  • main函数中先调用m.lock()持有锁
  • pipeline_func中调用m.unlock()释放锁,此时mutex已经处于未锁定状态
  • main函数最后又调用m.unlock(),这时候当前线程(main线程)并没有持有这个mutex的锁,触发了该警告。
    另外,mutex的lock和unlock必须严格成对出现,你的代码中一次lock对应两次unlock,本身就是不符合mutex使用规范的错误操作。

问题2:改写代码避免手动操作mutex

手动操作mutex容易出现锁未持有就解锁、锁泄漏等问题,推荐用条件变量(std::condition_variable)或者std::promise/std::future来实现这种一次性的线程同步逻辑,以下是两种可行方案:

方案1:使用条件变量(适合复杂同步场景)

#include <iostream>
#include <mutex>
#include <condition_variable>
#include <thread>

using namespace std::chrono_literals;

class Pipeline {
public:
    Pipeline() { std::cout << "Pipeline()\n"; };
    void init() { std::cout << "Pipeline::init()\n"; std::this_thread::sleep_for(3s); };
    void run() { while (true) { std::cout << "Pipeline::run()\n"; std::this_thread::sleep_for(1s); } };
};

class Connection {
public:
    Connection(Pipeline* p) { std::cout << "Connection()\n"; };
    void run() { while (true) { std::cout << "Connection::run()\n"; std::this_thread::sleep_for(1s); } };
};

void pipeline_func(Pipeline** pipeline, std::mutex& m, std::condition_variable& cv, bool& is_pipeline_ready) {
    *pipeline = new Pipeline();
    (*pipeline)->init();

    // 标记Pipeline就绪并通知等待线程
    {
        std::lock_guard<std::mutex> lock(m);
        is_pipeline_ready = true;
    }
    cv.notify_one();

    (*pipeline)->run(); // 无限运行
};

void connection_func(Pipeline** pipeline, std::mutex& m, std::condition_variable& cv, bool& is_pipeline_ready) {
    // 等待Pipeline初始化完成,自动管理锁的状态
    std::unique_lock<std::mutex> lock(m);
    cv.wait(lock, [&is_pipeline_ready](){ return is_pipeline_ready; });

    Connection connection(*pipeline);
    connection.run(); // 无限运行
};

int main() {
    Pipeline* pipeline = nullptr;
    std::mutex m;
    std::condition_variable cv;
    bool is_pipeline_ready = false;

    std::thread pipelineTh(pipeline_func, &pipeline, std::ref(m), std::ref(cv), std::ref(is_pipeline_ready));
    std::thread connectionTh(connection_func, &pipeline, std::ref(m), std::ref(cv), std::ref(is_pipeline_ready));

    pipelineTh.join();
    connectionTh.join();
}

方案2:使用std::promise/std::future(适合一次性结果传递)

#include <iostream>
#include <thread>
#include <future>

using namespace std::chrono_literals;

class Pipeline {
public:
    Pipeline() { std::cout << "Pipeline()\n"; };
    void init() { std::cout << "Pipeline::init()\n"; std::this_thread::sleep_for(3s); };
    void run() { while (true) { std::cout << "Pipeline::run()\n"; std::this_thread::sleep_for(1s); } };
};

class Connection {
public:
    Connection(Pipeline* p) { std::cout << "Connection()\n"; };
    void run() { while (true) { std::cout << "Connection::run()\n"; std::this_thread::sleep_for(1s); } };
};

void pipeline_func(Pipeline** pipeline, std::promise<Pipeline*>& prom) {
    *pipeline = new Pipeline();
    (*pipeline)->init();

    prom.set_value(*pipeline); // 传递初始化完成的Pipeline指针

    (*pipeline)->run(); // 无限运行
};

void connection_func(std::future<Pipeline*>& fut) {
    Pipeline* pipeline = fut.get(); // 等待Pipeline初始化完成,自动同步

    Connection connection(pipeline);
    connection.run(); // 无限运行
};

int main() {
    Pipeline* pipeline = nullptr;
    std::promise<Pipeline*> prom;
    std::future<Pipeline*> fut = prom.get_future();

    std::thread pipelineTh(pipeline_func, &pipeline, std::ref(prom));
    std::thread connectionTh(connection_func, std::ref(fut));

    pipelineTh.join();
    connectionTh.join();
}

改写思路说明

两种方案都遵循RAII原则,完全避免手动调用lock/unlock:

  1. 条件变量方案通过std::lock_guard和std::unique_lock自动管理锁的生命周期,wait方法会在等待期间自动释放锁、被唤醒后重新获取锁
  2. promise/future方案更简洁,内部封装了同步逻辑,仅需通过set_value和get完成线程间的结果传递与等待

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 08:26:36