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(); }
额外优化说明
- 新增花括号限制
lock_guard的作用域,确保输出完成后立刻释放锁; - 补充了
#include <chrono>头文件,原代码使用std::chrono::milliseconds但未包含对应头文件,会导致编译错误; - 析构函数中增加
joinable()判断,避免线程未启动时调用join()引发未定义行为。
内容的提问来源于stack exchange,提问作者rebelliousconformist
相关产品推荐
相关产品推荐

