如何让两个线程的循环交替执行(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)**和互斥锁,让线程执行完任务后主动通知对方,同时自己进入等待状态,直到被唤醒。
核心思路
- 用一个共享状态变量标记当前可执行的线程(比如
bool isATurn,true表示线程A执行,false表示主线程执行)。 - 每个线程进入循环后,先获取锁,然后检查状态是否符合自身执行条件:
- 不符合则等待条件变量,释放锁并进入休眠,直到被对方唤醒。
- 符合则执行任务,切换状态,通知对方线程,最后释放锁。
修正后的代码
#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
相关产品推荐
相关产品推荐

