Volatile变量学习 —— Volatile variables and their semantics in C/C++ vs Java

Most people think that volatile variables are for concurrency. In some sense, this intuition is correct. However, the semantics of volatile variables is different across different programming languages.

In C/C++, volatile variables are to prevent compilers from performing optimizations that may falsify the semantics of the code.

For example:

x=0;
while (x!=0) ;

In the above piece of code, an optimizing compiler can translate the program into

x=0;
while (true) ;

However, this optimization is dangerous because x might be changed by other threads. Making x "volatile" will prevent such an optimization.

理解:C++中,volatile变量的作用是防止编译器优化代码所导致的问题,比如上面的代码,编译器讲想想x!=0优化为true,这是很危险的,因为其他的线程中可能会改变x的值。所以讲x设置为volatile可以避免这种问题。

(Ref http://en.wikipedia.org/wiki/Volatile_variable)

In contrast, volatile keywords in Java help maintain orderings (happen-before relationships) of accesses to variables. Basically, each java threads are supposed to maintain their own "local" copy of the "main" memory and they only update the "main" memory when needed for efficiency. Therefore, different threads may have different views about a variable. Therefore, in order to ensure consistency, volatile keyword can be used to force a flush every time a thread accesses a volatile variable. As a result, the value of the variable in the "main" memory is always up-to-date. This means that all threads accessing a volatile variable have a consistent view of its value.

There are main differences between volatile and synchronized keywords. A volatile only synchronizes on its own value. When a thread accesses a volatile variable, only its value is flushed to the main memory. However, a synchronized synchronizes values of all variables in the thread's local memory. When a thread access a synchronized region (either a method or a block of code), it flushes all variables in its local memory.Therefore, synchronized incurs more overhead than volatile.

理解:Java中,volatile关键字可以用来保持变量的happen-before关系。基本上所有的线程本地都持有一份主存变量的拷贝,只有在需要的时候才会去更新主存,以提高效率。因此,变量的值在不同的线程中可能有所不同。因此,为了保持一致性,volatile变量保证每当一个线程操作有了一个volatile变量的时候,就需要对主存进行一次冲刷,以保持主存的值是最新的。这样就能保证变量的值在所有的线程中都是一致的。volatile变量和synchronized变量有很大的不同。当一个线程访问一个volatile变量,只需要刷新主存中这一个变量,而当线程进入一个同步块时,需要刷新同步块中的所有变量,也就是从主存中拷贝所有变量的值到本地。因此同步块比volatile会引发更多疼痛的问题。

 

For C#/Java, "volatile" tells the compiler that the value of a variable must never be cached as its value may change outside of the scope of the program itself. The compiler will then avoid any optimisations that may result in problems if the variable changes "outside of its control".

In C/C++, "volatile" is needed when developing embedded systems or device drivers, where you need to read or write a memory-mapped hardware device. The contents of a particular device register could change at any time, so you need the "volatile" keyword to ensure that such accesses aren't optimised away by the compiler

理解:C#和java中告诉编译器变量值永远不要被存储,因为它可能被程序外部改变。编译器将不会做任何优化,以避免产生问题。

 

posted on 2015-12-24 19:38  gyt929458988  阅读(210)  评论(0编辑  收藏  举报