可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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)?
回答1:
I've seen you asking about GCC in some comments, here you go.
GCC's Built-in functions for atomic memory access
回答2:
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
回答3:
Volatile variables do NOT imply memory barriers, and do not have the exchange
or compare_exchange_*
operations of std::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:
- volatile considered harmful
- Volatile: Almost Useless for Multi-Threaded Programming
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.
回答4:
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.
回答5:
There's a good summary of the diffs here, from Herb Sutter. In summary (cut and paste):
To safely write lock-free code that
communicates between threads without
using locks, prefer to use ordered
atomic variables: Java/.NET volatile,
C++0x atomic, and C-compatible
atomic_T.
To safely communicate with special
hardware or other memory that has
unusual semantics, use unoptimizable
variables: ISO C/C++ volatile.
Remember that reads and writes of
these variables are not necessarily
atomic, however.
回答6:
volatile
basically tells the compiler it can't make assumptions about what is in a particular memory location. For instance
bool test = true;
while(!test)
{
/* do something (e.g. wait) */
}
the compiler might optimize away the whole while
because it assumes test
is always true. If however test
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 in test
. We can tell the compiler that using volatile
.
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.