Я ошибся, выбрав std :: thread, чтобы назначить параллелизм потока. У меня нет времени изучать другой метод. Поэтому я надеюсь, что вы можете помочь мне здесь, я действительно запутался во всех этих типах мьютексов, обещаний, фьючерсов и т. Д. Отсутствие разнообразной документации/учебников удручает. Итак, я хочу, чтобы 3 потока (игроков) делали то же самое - выберите 2 случайных числа в качестве индексов для глобального 2-мерного массива, если значение ячейки равно 0, оно равно Идентификатору потока, в противном случае прекратите выполнение нить. Сделайте это в цикле, пока не останется только один поток. Мне нужно найти способ синхронизации трех потоков после каждой (до следующей) итерации, чтобы один поток не мог быть на 50-й итерации, в то время как другой включен, скажем, 30, т. Е. Поток должен дождитесь, пока все остальные завершат итерацию, прежде чем двигаться дальше. Мне нужен какой-то барьер. Я попытался использовать переменные условия, чтобы потоки спали до тех пор, пока последние финишные потоки не просветят их, но я не смог заставить их работать. Мои неудачные попытки закомментировано:C++ std :: thread synchronization in loop
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» вещь, которая будет выполнена только один поток (в зависимости от того что наступит раньше) на каждой итерации, но obiviously это не то, что я думал, что это было потому, что что приводит к некоторому странному поведению. Как это сделать? Хорошо, код может быть уродливым и все, что должно быть помещено внутри классов и методов или что-то в этом роде, но мне просто нужно получить эту работу независимо от того, насколько примитивно. Спасибо заранее!
Так что, если я получу это право, вы хотите, чтобы 3 потока случайным образом выбирали элемент массива, если он не равен нулю, потоки завершаются, иначе он пытается снова, и вы хотите, чтобы все потоки синхронизировались до тех пор, пока не осталось один ? – 111111
Вы не ошиблись при использовании 'std :: thread'. Вы ошиблись в том, что не понимаете основную многопоточность. – jalf
Да, но если его ненулевой, но равный Id, ничего не делайте, перейдите к следующей итерации. – andrisll