I'm trying to use 10 threads and each one needs to print his number and the printing needs to be synchronized. I'm doing it as homework and I have to use atomic variables to do it (no locks).
Here what I tried so far:
#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);
}
}
output example:
24
9143
541
2
8
expected output:
2
4
9
1
4
3
1
5
4
10
8
You have 2 bugs in your use of atomic
.
When compare_exchange_weak fails it stores the current value in the first parameter. If you want to keep trying the same value you need to set it back to the original value:
while ((turn.compare_exchange_weak(f, false)) == false)
{
f = true;
}
The second issue is that exchange
returns the currently stored value so:
turn = turn.exchange(true);
Sets the value of turn back to false, you need just:
turn.exchange(true);
Or even just:
turn = true;
Synchronisation isn't actually necessary in this case as std::cout
will do the synchronisation for you, single output operations wont overlap so you can just change your print
function to the following and it will just work:
void print(int i)
{
for (int j = 0; j < 100; j++)
{
cout << std::to_string(i) + "\n";
}
}
Atomics aren't the right approach to this problem, your code is incredibly slow. Mutexes would probably be quicker.