std::thread を選択してスレッドの同時実行数を割り当てるという間違いを犯しました。他の方法を学ぶ時間は残っていません。ここで私を助けてくれることを願っています。私は、これらすべての種類のミューテックス、プロミス、フューチャーなどについて本当に混乱しています。多様なドキュメント/チュートリアルの欠如は気のめいるようです。したがって、3 つのスレッド (プレイヤー) に同じことをさせたい - グローバルな 2D 配列のインデックスとして 2 つの乱数を選択し、セルの値が 0 の場合はスレッドの Id に等しく設定し、それ以外の場合はスレッドの実行を停止する. スレッドが 1 つだけになるまで、これをループで実行します。私が必要としているのは、1 つのスレッドが 50 回目の繰り返しにならないように (次の前に) 3 つのスレッドを同期する方法を見つけることです。他のすべての人が反復を完了してから先に進みます。何らかの障壁が必要です。条件変数を使用してスレッドをスリープ状態にし、最後の終了スレッドがスレッドを起動するように通知するまでスレッドをスリープ状態にしようとしましたが、動作させることができませんでした。私の失敗した試みはコメントアウトされています:
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」内の式は、反復ごとに 1 つのスレッド (どちらか早い方) によって実行されると予想していましたが、奇妙な動作が発生するため、明らかにそうではありませんでした。どうやってするか?わかりました、コードは醜いかもしれませんし、すべてをクラスやメソッドなどの中に入れる必要がありますが、どんなに原始的であっても、これを機能させる必要があります。前もって感謝します!