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

如何让两个线程的循环交替执行(ABABAB或BABABA模式)?

问题描述

我有一个问题,虽有类似问题的解答,但并不完全符合我的需求。我有两个线程,每个线程都包含一个循环,现在需要强制它们像触发器一样交替执行,即严格按照ABABAB或BABABA的模式运行,谁先启动不重要,但必须逐个执行。

我编写了一段简单的代码,但运行效果不佳,因为线程A会快速迭代并再次获取锁。我正在学习C++多线程技术,希望得到帮助。

注:假设是游戏场景,必须让玩家A和玩家B各执行一次循环。我也认同这种方式效率不高,同一时刻只有一个线程在工作,我只是想了解是否有实现方法。

附上现有代码:

int pointA , pointB;
std::mutex mtx; // 补充原代码遗漏的mutex定义

void testA()
{
    int i = 0;
    while (i < 10)
    {
        unique_lock<std::mutex> lck(mtx);
        cout << pointB << endl;
        pointA++;
        i++;
    }
}

int main() // 修正为标准C++的int返回类型
{
    int i = 0;
    pointA =100, pointB=0;
    thread t(testA);
    while (i < 10)
    {
        unique_lock<std::mutex> lck(mtx);
        cout << pointA << endl;
        pointB++;
        i++;
    }

    t.join();
    return 0;
}
解决方案

仅用std::mutex无法实现严格的线程交替执行——它只能保证互斥,无法控制执行顺序。要达成ABAB或BABABA的严格交替,需要结合**条件变量(std::condition_variable)**和互斥锁,让线程执行完任务后主动通知对方,同时自己进入等待状态,直到被唤醒。

核心思路

  1. 用一个共享状态变量标记当前可执行的线程(比如bool isATurn,true表示线程A执行,false表示主线程执行)。
  2. 每个线程进入循环后,先获取锁,然后检查状态是否符合自身执行条件:
    • 不符合则等待条件变量,释放锁并进入休眠,直到被对方唤醒。
    • 符合则执行任务,切换状态,通知对方线程,最后释放锁。

修正后的代码

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

using namespace std;

int pointA, pointB;
mutex mtx;
condition_variable cv;
bool isATurn = false; // 初始让主线程先执行,设为true则线程A先启动

void testA()
{
    int i = 0;
    while (i < 10)
    {
        unique_lock<mutex> lck(mtx);
        // 等待直到轮到自己执行
        cv.wait(lck, []{ return isATurn; });
        
        // 执行游戏逻辑
        cout << "玩家A执行: 当前pointB = " << pointB << endl;
        pointA++;
        i++;
        
        // 切换执行权限,通知主线程
        isATurn = false;
        cv.notify_one();
    }
}

int main()
{
    int i = 0;
    pointA = 100, pointB = 0;
    thread playerATask(testA);
    
    while (i < 10)
    {
        unique_lock<mutex> lck(mtx);
        // 等待直到轮到自己执行
        cv.wait(lck, []{ return !isATurn; });
        
        // 执行游戏逻辑
        cout << "玩家B执行: 当前pointA = " << pointA << endl;
        pointB++;
        i++;
        
        // 切换执行权限,通知玩家A线程
        isATurn = true;
        cv.notify_one();
    }
    
    playerATask.join();
    return 0;
}

代码说明

  • std::condition_variable::wait会自动释放持有的锁,进入等待状态;当被唤醒时,会重新获取锁并检查条件是否满足,只有条件成立才会继续执行,避免虚假唤醒。
  • notify_one用于唤醒等待在该条件变量上的一个线程,确保对方可以继续执行。
  • 修改初始的isATurn值,就能切换是ABAB还是BABABA的执行顺序,满足启动顺序的需求。

备选实现:双条件变量

如果觉得单状态变量不够直观,可以用两个条件变量分别标记对方的执行权限,逻辑更清晰:

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

using namespace std;

int pointA, pointB;
mutex mtx;
condition_variable playerACond, playerBCond;
bool playerAReady = false;

void playerATask()
{
    int i = 0;
    while (i < 10)
    {
        unique_lock<mutex> lck(mtx);
        playerACond.wait(lck, []{ return playerAReady; });
        
        cout << "玩家A执行: 当前pointB = " << pointB << endl;
        pointA++;
        i++;
        
        playerAReady = false;
        playerBCond.notify_one(); // 通知玩家B线程执行
    }
}

int main()
{
    int i = 0;
    pointA = 100, pointB = 0;
    thread t(playerATask);
    
    while (i < 10)
    {
        unique_lock<mutex> lck(mtx);
        // 主线程(玩家B)先执行
        cout << "玩家B执行: 当前pointA = " << pointA << endl;
        pointB++;
        i++;
        
        playerAReady = true;
        playerACond.notify_one(); // 通知玩家A执行
        playerBCond.wait(lck, []{ return !playerAReady; }); // 等待玩家A完成
    }
    
    t.join();
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 00:25:51