我选择 std::thread 进行线程并发分配时犯了一个错误。我没有时间学习其他方法。所以我希望你能在这里帮助我,我真的对所有这些类型的互斥锁、承诺、期货等感到困惑。缺乏多样化的文档/教程令人沮丧。所以我希望 3 个线程(玩家)做同样的事情 - 选择 2 个随机数作为全局二维数组的索引,如果单元格的值为 0,则将其设置为等于线程的 ID,否则停止线程的执行. 循环执行此操作,直到只剩下一个线程。我需要的是找到一种方法在每次(下一次)迭代之后同步 3 个线程,这样一个线程不能在第 50 次迭代,而另一个线程在第 30 次迭代,即线程必须等待让所有其他人在继续之前完成迭代。我需要某种屏障。我尝试使用条件变量让线程进入睡眠状态,直到最后一个完成线程发出信号来唤醒它们,但我无法让它工作。我不成功的尝试被注释掉:
std::mutex GridMutex, FinishMutex, LeftMutex;
int Grid[X][Y], Finished = 0, PlayersLeft = 3;
void Fight(int Id) {
int RandX, RandY, i = 0;
std::random_device rd; // access random device
std::mt19937 e(rd()); // seed the engine
std::uniform_int_distribution<int> r1(0, X-1);
std::uniform_int_distribution<int> r2(0, Y-1);
LeftMutex.lock(); // mutex on PlayersLeft
while (PlayersLeft != 1) {
++i;
/*std::call_once(flag, [Id, i](){*/std::cout << " Round " << i << " Left: " << PlayersLeft << '\n';/*});*/
LeftMutex.unlock();
// FinishMutex.lock();
// std::call_once(flag, [](){Finished = 0;});
// FinishMutex.unlock();
RandX = r1(e);
RandY = r2(e);
GridMutex.lock();
if (Grid[RandX][RandY] != Id) {
if (Grid[RandX][RandY] == 0) {
Grid[RandX][RandY] = Id;
std::cout << "i= "<< i << " Thread " << Id << " occupied cell " << RandX << RandY << '\n';
std::chrono::milliseconds sleepDuration(100);
std::this_thread::sleep_for(sleepDuration); //just to lock the grid for some time
GridMutex.unlock();
}
else {
GridMutex.unlock();
LeftMutex.lock();
--PlayersLeft;
LeftMutex.unlock();
break; //stop thread if cell occupied
}
}
//Wait for the others here
// FinishMutex.lock();
// ++Finished;
// if (Finished == 3) {
// FinishMutex.unlock();
// AllReady.notify_all();
// }
// else {
// FinishMutex.unlock();
// AllReady.wait(Lk, [](){return Finished == 3;});
// Lk.unlock();
// }
LeftMutex.lock();
}
}
int main() {
SetGrid();
std::thread t1(&Fight, 1);
std::thread t2(&Fight, 2);
std::thread t3(&Fight, 3);
t1.join();
t2.join();
t3.join();
GetGrid();
return 0;
}
我希望“call_once”事物中的表达式在每次迭代中仅由一个线程(以先到者为准)执行,但显然这不是我认为的那样,因为这会导致一些奇怪的行为。怎么做?好的,代码可能很难看,应该放在类和方法之类的东西中,但无论多么原始,我都需要让它工作。先感谢您!