Volatile是神马

来源:互联网 发布:荣威质量 知乎 编辑:程序博客网 时间:2024/04/28 23:08

曾经面试被问到过一次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++的作用很不相同:

  • 所有的java版本中,对一个volatile变量有一个全局的读写顺序. 这意味着每个访问该volatile变量的读操作总是返回当前的值,而不是使用的是一个cache的值. 然而, 它与C/C++中一样,如果是在多线程的环境下,多个线程对同一个变量的读写之间的顺序是不被保证的.
  • 在java 5及其之后的版本中, 实现了对volatile变量的读写操作的获得并释放的类似mutex的动作.

从以上可以看出, 使用volatile变量比使用lock要快, 但是它不适用于一些场合.  在java 5中对其有所表现; 例如, double-checked locking现在工作的正确了.
// Works with acquire/release semantics for volatile// Broken under Java 1.4 and earlier semantics for volatileclass 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