синхронизация 10 потоков с atomi c bool - PullRequest
1 голос
/ 25 января 2020

Я пытаюсь использовать 10 потоков, и каждый из них должен напечатать свой номер, и печать должна быть синхронизирована. Я делаю это как домашнее задание и для этого мне нужно использовать переменные atomi c (без блокировок).

Вот что я пробовал до сих пор:

#include <atomic>
#include <thread>
#include <iostream>
#include <vector>

using namespace std;
atomic<bool> turn = true;

void print(int i);

int main()
{
  vector<thread> threads;

  for (int i = 1; i <= 10; i++)
  {
    threads.push_back(thread(print, i));
  }

  for (int i = 0; i < 10; i++)
  {
    threads[i].join();
  }

  return 0;
}


void print(int i)
{
  bool f = true;
  for (int j = 0; j < 100; j++)
  {
    while((turn.compare_exchange_weak(f, false)) == false)
    { }
    cout << i << endl;
    turn = turn.exchange(true);
  }
}

пример вывода:

24 

9143 
541 

2 
8

ожидаемый результат:

2
4
9
1
4
3
1
5 
4
10
8

1 Ответ

3 голосов
/ 25 января 2020

При использовании atomic.

у вас есть 2 ошибки. При сбое compare_exchange_weak текущее значение сохраняется в первом параметре. Если вы хотите продолжать пробовать одно и то же значение, вам нужно установить его обратно в исходное значение:

while ((turn.compare_exchange_weak(f, false)) == false)
{
  f = true;
}

Вторая проблема заключается в том, что exchange возвращает текущее сохраненное значение так:

turn = turn.exchange(true);

Устанавливает значение поворота обратно в false, вам нужно просто:

turn.exchange(true);

Или даже просто:

turn = true;

В этом случае синхронизация на самом деле не нужна, так как std::cout выполнит синхронизацию за вас, отдельные операции вывода не будут перекрываться, так что вы можете просто изменить свою print функцию на следующую, и она будет просто работать:

void print(int i)
{
    for (int j = 0; j < 100; j++)
    {
        cout << std::to_string(i) + "\n";
    }
}

Атомика не правильный подход к этому проблема, ваш код невероятно медленный Мьютексы, вероятно, будут быстрее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...