曾经面试被问到过一次Volatile的含义, 因为当时的一段时间一直比较多的用java, 单只回答了java处的含义, 记不太清楚C中的内涵了, 这次正好又查东西链接到相关的资料, 就记下来复习复习:)
C/C++中的作用:
- 允许访问memory mapped设备(比如,一个指针,指向的是一个硬件寄存器)
- 允许在setjmp和longjmp之间使用该变量 (长跳转之后该变量还有意义)
- 允许在signal handler中使用sig_atomic_t的变量 (通常这个类型的变量也会声明为volatile, 参考资料3)
通常来说, 任何会被异步更新的变量都应该被用volatile声明. 但是这里不包扩CPU会把变量保存到register中的情况.
它告诉编译器生成的代码中,对该变量每次使用的时候都会reload它,而不是只拿已经load到register中值来用.
对volatile变量的操作不是原子的, 使用它们的线程也不能保证相互之间的顺序性(即如果几个线程不加保护的使用它,不能保证操作它的顺序).
请注意, 如果使用-O2,通常gcc不会对没有声明为volatile的变量在每次使用时,从内存中重新载入值到寄存器, 而只是用寄存器中的值.
当然,volatile的性能肯定比register差, 所以如果不需要使用volatile, 请不要滥用.
JAVA中:
它与C/C++的作用很不相同:
从以上可以看出, 使用volatile变量比使用lock要快, 但是它不适用于一些场合. 在java 5中对其有所表现; 例如, double-checked locking现在工作的正确了.
- 所有的java版本中,对一个volatile变量有一个全局的读写顺序. 这意味着每个访问该volatile变量的读操作总是返回当前的值,而不是使用的是一个cache的值. 然而, 它与C/C++中一样,如果是在多线程的环境下,多个线程对同一个变量的读写之间的顺序是不被保证的.
- 在java 5及其之后的版本中, 实现了对volatile变量的读写操作的获得并释放的类似mutex的动作.
// Works with acquire/release semantics for volatile // Broken under Java 1.4 and earlier semantics for volatile class Foo { private volatile Helper helper = null; public Helper getHelper() { Helper result = helper; if (result == null) { synchronized(this) { result = helper; if (result == null) { helper = result = new Helper(); } } } return result; } // other functions and members... }
参考资料:
http://en.wikipedia.org/wiki/Volatile_variable
http://www.kcomputing.com/volatile.html
http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html