I'm using linux and I have two variable that is read/write in another thread. Once in a while (100ms) ThreadB reads the status of the variables and does something. It's basically a while(1){ dosomething(); usleep(); }
. I'm worried the variables will be cached and never updated.
What's the best way to ensure the loop will work after optimizations? I am thinking volatile
should do the job but I hear it doesn't work sometimes. Both loops don't run frequently (10ms+). What's the most simple and straightforward way to access them? I'm using C++11
I'm a little unsure how to use std::atomic<int>
. Can I just use it like a normal int variable and it will work as expected?
You can indeed just declare it as
std::atomic<int>
, and things should work as you want.volatile
is about preserving the sequence of addresses and values that the generated code must present to the processor for reading/writing. It doesn't at all constrain what the hardware does with that for purposes of memory consistency, which is the concern ofatomic
. Here's an article from Intel explaining this difference.The C and C++ standards (from 2011 onwards) define a memory model that describes what operations are or aren't defined according to the language, and what values an expression can produce if the program as a whole is well-defined.
According to the standards, any program doing unsynchronized access by multiple threads to a single object (e.g. your shared
int
), in which at least once access is a write, is undefined. Declaring a variablevolatile
doesn't make accesses to it synchronized. Accesses to variables declared asatomic
are always synchronized, by definition.In the default case, if you just use
atomic<int>
without changing anything else about how you use it, you'll get what are known as sequentially consistent accesses, which are the most strongly coordinated between threads, and hence potentially most costly. For your use case, that doesn't seem to be a concern - the cost is on the order of nanoseconds to microseconds, while you're polling in milliseconds. If you did need to optimize further, you could potentially specify less restrictive accesses.