I have read many of the questions already answered that relate to this but none of them gave me a clear understanding of which I should be using when I have multiple writers but a single reader. The code below is a contrived example of what I'm talking about.
struct StateInfo {
long wd{};
uint32_t perc{};
};
class Blah
{
const int numDevices = getDevices();
std::shared_mutex sharedMutexSI_;
vector<StateInfo> stateInfo;
public:
Blah() : stateInfo(numDevices){};
void writers(StateInfo &newSi, const int i)
{
std::shared_lock<std::shared_mutex> _MULTIPLE(sharedMutexSI_);
stateInfo[i] = newSi;
}
StateInfo reader(const int i)
{
std::lock_guard<std::shared_mutex> _EXCLUSIVE(sharedMutexSI_);
return stateInfo[i];
}
};
The situation is that multiple writers may simultaneously update the stateInfo vector but never the same item in the vector as i
is unique to each thread. A single reader thread may at any time try to read any of the vector items.
Is the above code correct in avoiding race conditions?
Is
lock_guard
the right one to use or should I usescoped_lock
orunique_lock
?
lock_guard
,scoped_lock
andunique_lock
in this use case – Metallong
on your platform you could changeStateInfo
tostd::atomic<uint64_t>
and avoid locking all together – Metallock_guard
is the right one as it is the simplest and the others don't add anything useful in this case? – Restivelock_guard
andscoped_lock
are fine,unique_lock
is an overkill. – Tolentinolock_guard
is the simplest and if I don't need the functionality ofscoped_lock
, then I should stick with the simplest? – Restivelock_guard
andscoped_lock
are identical in their implementation. – Tolentino> 0
) all readers and writers of X must be synchronised. Then it depends on how many synchronisation primitives (e.g. mutex) is acceptable. With exactly one primitive, all readers and writers must use it (so all writers synchronise with each other and the reader). Ifn
mutexes (n
= number of elements) is acceptable, then each writer can use its own primitive (and not synchronise with other writers) but the reader must grab the corresponding primitive before reading each element (i.e. synchronise with all writers). – Kolalock_guard
,scoped_lock
andunique_lock
: see a dedicated question with answers here. – Inaeshared_lock
for writing andscope_lock
for reading? That is opposite of what you want. Useshared_lock
for reading andscope_lock
for writing. – Benjaminbenjistd::mutex
or just make theStateInfo
atomic. In any case the class suffers from false-sharing so I am not sure if shared lock helps much. – Benjaminbenji