gpt4 book ai didi

循环内的 C++ std::thread 同步

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:32:31 25 4
gpt4 key购买 nike

我错误地选择了 std::thread 来进行线程并发分配。我没有时间学习其他方法。所以我希望你能在这里帮助我,我真的很困惑所有这些类型的互斥体、 promise 、 future 等。缺乏多样化的文档/教程令人沮丧。所以我希望 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”中的表达式在每次迭代中仅由一个线程(以先到者为准)执行,但显然这不是我想的那样,因为这会导致一些奇怪的行为。怎么做?好的,代码可能很丑陋,所有这些都应该放在类和方法或其他东西中,但无论多么原始,我只需要让它工作。提前致谢!

最佳答案

您可以使用 atomic variables 移除一些锁像 std::atomic_intstd::atomic_bool(或 std::atomic_flag

接下来,不要自己进行锁定和解锁,而是为此使用 RAII 包装器,例如 std::lock_guard .这将锁定指定的互斥锁,直到锁定对象本身被销毁(通常是在它超出范围时)。

现在,虽然使用这些东西会极大地改进您的代码,但您实际的逻辑错误非常简单:您不应该与常量 3 进行比较,而应该与 playersLeft 进行比较。请注意,由于条件取决于此,因此您还必须在更改此变量时发出信号。

关于循环内的 C++ std::thread 同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10354472/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com