- 允许访问内存映射设备
- 在setjmp和longjmp之间使用变量
- 在信号处理程序中使用变量
- 忙等待
显式同步也可以实现这一点,但我们通常不希望锁定一个值。双重检查锁定就是其中的经典例子(摘自维基百科)。确保对变量的更新可预测地传播到其他线程
// 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() {
if (helper == null) {
synchronized(this) {
if (null == helper)
helper = new Helper();
}
}
return helper;
}
// other functions and members...
}
这里有一个很好的解释:http://en.wikipedia.org/wiki/Volatile_variable,但是简单来说,它告诉编译器不要假设变量不会被其他人访问,并且将其优化为寄存器并仅更新寄存器而不是实际存储是致命的。
volatile关键字早在C语言中就出现了,它的基本作用是“关闭”一些编译器优化,这些优化假设如果一个变量没有被显式地改变,那么它就没有被改变过。它主要用于声明由中断处理程序更改的变量。例如,我曾经(80年代末)使用它来声明包含鼠标光标位置的全局变量。该位置由中断更改,如果没有使用volatile,主程序有时无法检测到其更改,因为编译器优化了变量访问,认为它不必要。
今天,这些用途通常已经过时了(除非您编写低级操作系统代码),但仍然存在一些罕见情况下需要使用volatile(确实非常罕见-例如,我可能已经7年没有使用它了)。
但对于多线程编程来说,它完全不推荐使用。问题在于它不能保护线程之间的并发访问,它只会消除同一线程中防止其“刷新”的优化。它并不适用于多线程环境。如果您使用Java,请使用synchronized。如果您使用C ++,请使用一些同步库,如pthreads或Boost.Threads(或者最好使用新的C ++ 0X线程库,如果可以的话)。
我已经有一段时间没有使用C++了,我真的不记得在那种语言中volatine的定义。但是Java语言规范明确指出volatile的目的是为了促进对变量的多线程访问。引用:“一个字段可以被声明为volatile,在这种情况下,Java内存模型(§17)确保所有线程看到变量的一致值。”他们继续说,对volatile值的引用保证按照它们在代码中指定的顺序满足,即如果您声明i和j为volatile,然后写入“++i; ++j”,那么实际上i将始终在j之前递增。
我唯一记得在Java中使用volatile的时候是当我有一个线程可能设置取消标志,另一个线程循环执行一些大操作,并且每次通过循环检查取消标志。这确实像我预期的那样工作。
我同意“volatile”具有非常有限的用处。大多数多线程需要在某个时刻进行“同步”。但是“有限”和“没有”并不是同一件事。余弦函数在大多数商业应用程序中的用处非常有限。但是当你需要它时,哇,那就省了很多麻烦。
当一个变量可以被多个线程访问,并且您希望在每个指令中,您的代码都能获取该变量的更新值时,应使用Volatile变量。
编译器通常会优化代码并将变量存储在寄存器中,而不是每次从内存中获取变量(如果它们发现没有人更新它)。
但是通过使用volatile,您可以强制编译器每次获取更新的值。