volatile能否用于多线程的数据同步(线程安全)?
答案是不能!!
以前网上很多资料说用volatile实现无锁,但这样是行不通的。
相关参考:
Why is volatile not considered useful in multithreaded C or C++ programming?
http://stackoverflow.com/questions/2484980/why-is-volatile-not-considered-useful-in-multithreaded-c-or-c-programming
Stay away from Volatile in threaded code?
https://sites.google.com/site/kjellhedstrom2/stay-away-from-volatile-in-threaded-code
When to use volatile with multi threading?
http://stackoverflow.com/questions/4557979/when-to-use-volatile-with-multi-threading
Short & quick answer: volatile
is (nearly) useless for platform-agnostic, multithreaded application programming. It does not provide any synchronization, it does not create memory fences, nor does it ensure the order of execution of operations. It does not make operations atomic. It does not make your code magically thread safe. volatile
may be the single-most misunderstood facility in all of C++. See this, this and this for more information about volatile
On the other hand, volatile
does have some use that may not be so obvious. It can be used much in the same way one would use const
to help the compiler show you where you might be making a mistake in accessing some shared resource in a non-protected way. This use is discussed by Alexandrescu in this article. However, this is basically using the C++ type system in a way that is often viewed as a contrivance and can evoke Undefined Behavior.
volatile
was specifically intended to be used when interfacing with memory-mapped hardware, signal handlers and the setjmp machine code instruction. This makes volatile
directly applicable to systems-level programming rather than normal applications-level programming.
The 2003 C++ Standard does not say that volatile
applies any kind of Acquire or Release semantics on variables. In fact, the Standard is completely silent on all matters of multithreading. However, specific platforms do apply Acquire and Release semantics on volatile
variables.
[Update for C++11]
The C++11 Standard now does acknowledge multithreading directly in the memory model and the lanuage, and it provides library facilities to deal with it in a platform-independant way. However the semantics of volatile
still have not changed. volatile
is still not a synchronization mechanism. Bjarne Stroustrup says as much in TCPPPL4E:
Do not use
volatile
except in low-level code that deals directly with hardware.Do not assume
volatile
has special meaning in the memory model. It does not. It is not -- as in some later languages -- a synchronization mechanism. Sto get synchronization, useatomic
, amutex
, or acondition_variable
.
[/End update]
The above all applies the the C++ language itself, as defined by the 2003 Standard (and now the 2011 Standard). Some specific platforms however do add additional functionality or restrictions to what volatile
does. For example, in MSVC 2010 (at least) Acquire and Release semantics do apply to certain operations on volatile
variables. From the MSDN:
When optimizing, the compiler must maintain ordering among references to volatile objects as well as references to other global objects. In particular,
A write to a volatile object (volatile write) has Release semantics; a reference to a global or static object that occurs before a write to a volatile object in the instruction sequence will occur before that volatile write in the compiled binary.
A read of a volatile object (volatile read) has Acquire semantics; a reference to a global or static object that occurs after a read of volatile memory in the instruction sequence will occur after that volatile read in the compiled binary.
However, you might take note of the fact that if you follow the above link, there is some debate in the comments as to weather or not acquire/release semantics actually apply in this case.