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

C++类内创建两个并发线程仅一个运行的问题排查

问题分析与解决

你的问题核心是**std::this_thread::sleep_for被放在了std::lock_guard的作用域内**,导致锁被持有整整1秒,第二个线程完全无法获取锁,只能持续阻塞,看起来像是从未执行。

错误原因详解

std::lock_guard会在构造时加锁,析构时自动解锁。你的代码中,sleep操作处于锁的保护范围内:第一个线程拿到锁后,会持有锁直到sleep完成才释放。这1秒内第二个线程一直处于等待锁的状态;而当锁被释放后,第一个线程会立刻再次进入循环重新获取锁(线程调度机制会让正在运行的线程更容易抢到锁),导致第二个线程几乎没有机会执行。

修正方案

把sleep操作移到std::lock_guard的作用域之外,让锁只在输出时短暂持有,输出完成后立刻释放,两个线程就能交替获取锁执行输出。

修正后的代码

#include <thread>
#include <string>
#include <iostream>
#include <mutex>
#include <chrono> // 补充缺失的chrono头文件

// 全局互斥锁
std::mutex m_printmutex;

class Class
{
public:
    Class(const std::string& s, const int& i) : m_data(s), threadName(i) { }
    ~Class() { 
        // 先判断线程是否可join,避免未启动线程引发的错误
        if (m_thread.joinable()) {
            m_thread.join(); 
        }
        if (m_thread2.joinable()) {
            m_thread2.join();
        }
    }
    void runThread() { 
        m_thread = std::thread(&Class::print, this); 
        m_thread2 = std::thread(&Class::print,this);
    }

private:
    std::string m_data;
    std::thread m_thread;
    std::thread m_thread2;
    int threadName;
    void print()  { 
        while(1){
            { // 用花括号明确lock_guard的作用域
                std::lock_guard<std::mutex> lg(m_printmutex);
                std::cout << "thread # " << std::this_thread::get_id() << " "  << m_data << '\n'; 
            } // lock_guard在此析构,释放锁
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        }
    }
};

int main()
{
    Class c("Hello, world!",1);
    c.runThread();
}

额外优化说明

  1. 新增花括号限制lock_guard的作用域,确保输出完成后立刻释放锁;
  2. 补充了#include <chrono>头文件,原代码使用std::chrono::milliseconds但未包含对应头文件,会导致编译错误;
  3. 析构函数中增加joinable()判断,避免线程未启动时调用join()引发未定义行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 05:53:14