Reputation: 659
A class has the following member,
std::atomic<int> clientId{0};
And given the following inside it's member function,
int currentId = ++clientId.load();
Is there a race condition here? I am trying to do something similar to generate clientId's. Multiple threads could execute this part of the code. Can a thread that has incremented clientId and before it tries to load() and get a copy, another thread increment the same and thus end up with a race condition? If yes, is protecting with a mutex the best way using an ordinary int and getting a copy inside the mutex?
Please explain.
Upvotes: 1
Views: 687
Reputation: 37606
std::atomic<int>::load()
does not return a reference, so you are not incrementing the current value of clientId
, you are incrementing the temporary returned by load()
.
You need to do:
int currentId = ++clientId; // no .load()
There are overloaded operators for std::atomic
. The memory order for the pre-increment operator is std:: memory_order_seq_cst
1, which says:
A load operation with this memory order performs an acquire operation, a store performs a release operation, and read-modify-write performs both an acquire operation and a release operation, plus a single total order exists in which all threads observe all modifications in the same order (see Sequentially-consistent ordering below)
So you are safe from data-race condition here.
1 The standard says that ++clientId
is equivalent to fetch_add(1) + 1
, and the default memory order for fetch_add
is std::memory_order_seq_cst
.
Upvotes: 4