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

使用线程、条件变量和互斥锁打印奇偶无输出,求排查指导

问题分析与修复

你的代码没有输出的核心原因是两个线程启动后立刻进入条件变量的等待状态,且没有任何线程触发唤醒操作,同时wait调用缺少条件判断,无法正确控制线程执行时机。

具体问题点

  1. 初始无唤醒信号:主线程启动t1和t2后,两个线程都会在获取锁后调用cv.wait(locker),此时没有任何线程调用notify_all(),导致两个线程永久阻塞,无法继续执行后续打印逻辑。
  2. wait缺少条件谓词:即使有唤醒信号,wait可能会遇到虚假唤醒,且无法判断当前是否是自己该执行的时机(比如偶数线程不该在i为奇数时执行)。
  3. 初始值匹配问题:全局变量i=0是偶数,应该让偶数线程先执行,但当前逻辑没有区分线程执行的条件。

修复后的代码

#include <iostream>
#include <thread>
#include <condition_variable>
using namespace std;

condition_variable cv;
mutex mtx;
int i = 0;

void printeven() {
    for (; i < 100;) {
        unique_lock<mutex> locker(mtx);
        // 等待直到i是偶数且未超过范围
        cv.wait(locker, []{ return (i % 2 == 0) && (i < 100); });
        cout << "from even " << i << endl;
        i += 2;
        cv.notify_all();
    }
}

void printodd() {
    for (; i < 100;) {
        unique_lock<mutex> locker(mtx);
        // 等待直到i是奇数且未超过范围
        cv.wait(locker, []{ return (i % 2 == 1) && (i < 100); });
        cout << "from odd " << i << endl;
        i += 2;
        cv.notify_all();
    }
}

int main() {
    cout << "Hello World" << endl;

    thread t1(printeven);
    thread t2(printodd);
    // 主线程启动后先唤醒一次,让偶数线程开始执行
    cv.notify_all();
    
    t1.join();
    t2.join();

    return 0;
}

修复说明

  • 添加wait的条件谓词:通过lambda表达式判断当前线程是否应该执行(偶数线程等待i为偶数,奇数线程等待i为奇数),同时避免虚假唤醒。
  • 主线程初始唤醒:在启动线程后调用cv.notify_all(),触发第一个线程(偶数线程,因为i=0)开始执行。
  • 移除多余调试输出:去掉了原代码中重复的enter even/odd输出,让逻辑更清晰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 19:33:28