I need to have atomic variables in my program. Previously I was using std::atomic<int>
, but the platform in which I'm working now does not have a g++ compiler that supports C++0x. I used volatile int
and it seems to be working, as I haven't experienced a race condition yet in the multicore system I'm testing it on.
My question is if volatile int
is atomic like std::atomic<int>
? Also, does it creates memory barriers (which I also require)?
I've seen you asking about GCC in some comments, here you go.
GCC's Built-in functions for atomic memory access
Volatile variables do NOT imply memory barriers, and do not have the
exchange
orcompare_exchange_*
operations ofstd::atomic
. They do avoid the compiler lifting a load into multiple loads on the machine code level (and vice versa, and similar for stores) but that's it.You may be interested in these articles:
If you do not have
std::atomic
, you may want to use boost::atomic, or use the low-level barrier and atomic-operation primitives offered by whatever compiler you're using.No.
volatile
has nothing to do with multithreading. It doesn't enforce a memory barrier (although some compilers might choose to add that anyway), and it makes no guarantees about read/write reordering with respect to non-volatile objects.volatile
was added to support writing to memory-mapped hardware I/O registers, and such cases, where it is important that your write isn't optimized away, but no precise ordering guarantees wrt. non-volatile reads/wrties are required.You might also want to read this
volatile
basically tells the compiler it can't make assumptions about what is in a particular memory location. For instancethe compiler might optimize away the whole
while
because it assumestest
is always true. If howevertest
is at some point going to be updated from elsewhere (some hardware or another thread for instance) the we do not want the compiler to assume it knows what is intest
. We can tell the compiler that usingvolatile
.As the other answers say, it gives no guarantees about what order things access the memory location in.
P.s. I shamelessly stole that example from somewhere but can't remember where I saw it.
Before C++0x, the language wasn't thread aware, so it did not prevent multiple access. Declaring it volatile will help some, but it won't prevent races.
See http://en.wikipedia.org/wiki/Volatile_variable for more details.
To truly make operations atomic, you'll need to employ whatever locking mechanism your threading library (win32 threads, pthreads, etc) provides.
There's a good summary of the diffs here, from Herb Sutter. In summary (cut and paste):