如何用条件变量修复线程交替打印中的死锁问题?
解决多线程循环打印a/b/c的死锁问题
问题根源
原代码存在两个核心问题导致偶尔无输出或死锁:
- 通知丢失:主线程启动线程后立刻调用
var_a.notify_one(),此时线程A可能还未完成初始化进入等待状态,通知直接被丢弃,所有线程卡在wait无法继续。 - 虚假唤醒:
std::condition_variable::wait可能发生系统层面的虚假唤醒,没有谓词校验的话,线程会错误执行,破坏打印顺序甚至引发死锁。
修复后的代码
#include <iostream> #include <mutex> #include <condition_variable> #include <thread> // 共享状态:标记当前允许打印的字符 char current_char = 'a'; void print( std::mutex& mutex, std::condition_variable& cv, int count, char target_ch, char next_ch) { std::unique_lock<std::mutex> lock(mutex); for (int i = 0; i < count; ++i) { // 等待直到轮到当前线程打印(带谓词避免虚假唤醒) cv.wait(lock, [target_ch](){ return current_char == target_ch; }); std::cout << target_ch; // 更新状态为下一个要打印的字符 current_char = next_ch; // 通知所有线程检查状态 cv.notify_all(); } }; int main() { const int count = 10; std::condition_variable cv; std::mutex mutex; auto thread_a = std::thread(&print, std::ref(mutex), std::ref(cv), count, 'a', 'b'); auto thread_b = std::thread(&print, std::ref(mutex), std::ref(cv), count, 'b', 'c'); auto thread_c = std::thread(&print, std::ref(mutex), std::ref(cv), count, 'c', 'a'); thread_a.join(); thread_b.join(); thread_c.join(); std::cout << std::endl; return 0; }
关键优化点
- 用**共享变量
current_char**统一控制打印顺序,每个线程通过wait的谓词判断是否轮到自己,彻底解决通知丢失和虚假唤醒问题。 - 所有线程共用一个
condition_variable,每次打印后更新状态并通知所有线程,线程自行校验状态,简化了多条件变量的复杂依赖。 - 逻辑更清晰,避免了原代码中线程启动顺序与通知时机不匹配的问题。
内容的提问来源于stack exchange,提问作者mascai
相关产品推荐
相关产品推荐

