在C/C++/Java中使用volatile说明符

Ank*_*kur 5 c++ java volatile

在多线程编程上经历许多资源时,通常会出现对volatile说明符的引用.很明显,使用此关键字并不是在C/C++和Java(版本1.4及更早版本)中实现多个线程之间同步的可靠方法.以下是维基百科列出(不解释如何)作为此说明符的典型用法: -

  1. 允许访问内存映射设备
  2. 允许在setjmp和longjmp之间使用变量
  3. 允许在信号处理程序中使用变量
  4. 忙着等待

我可以开始在上面列出的用法中看到这个说明符的作用,但由于我还没有完全理解这些区域中的每一个,我无法弄清楚这个说明符在每个用法中的行为.

有人能解释一下吗

zeb*_*box 12

您的问题在技术上被称为"一罐蠕虫"!对于c/c ++(我不能评论java)
你可以非常粗略地总结volatile作为编译器的指令,说"请不要优化它",但是专业人士之间有很多争论,关于是否它是
a)对内核级代码有用 <-Edit基于反馈澄清
b)甚至大多数编译器都正确实现.

此外,不要将它用于多线程编程,这里有一个很好的解释为什么

=编辑=有趣的是,它的价值.丹尼斯里奇反对它的包容(以及常量)详情点击这里


dbo*_*rba 6

由于您对这些用例感兴趣,我将解释第一个用例.请注意,这适用于ac/c ++的角度,不知道它如何在java中起作用,尽管我怀疑c/c ++中的volatile通常用于完全不同的情况.

存储器映射设备是处理器以与存储器相同的方式而不是通过特殊总线与之通信的外围设备.

假设你有一个带有内存映射定时器的灯.您通过将1写入其内存地址来打开指示灯并且其内部计时器倒计时5秒钟并关闭指示灯并将内存位置重置为0.现在您正在开发需要在某些事件后打开指示灯的交流程序,有时在柜台到期前将其关闭.如果使用常规变量(往往是此类应用程序的指针或引用)来写入其内存位置,则由于编译器优化,可能会出现许多问题.

如果你没有使用那么多的变量而且你正在打开它并且在关闭它之后没有任何其他变量使用该值 - 有时编译器将完全摆脱第一个赋值,或者在其他情况下它将只需保持处理器寄存器中的值,永远不要写入内存.在这两种情况下,光线都不会打开,因为它的记忆从未改变过.

现在想想另一种情况,你可以检查灯的状态并且它已经打开.这里,该值从器件的存储器中提取并保存在处理器寄存器中.现在,几秒钟后,灯自动关闭.此后不久,您尝试再次打开灯,但是因为您读取了该内存地址并且之后没有更改它,编译器会假定该值仍为1,因此永远不会更改它,尽管它现在实际上是0.

通过使用易失性关键字,可以防止编译器在将代码转换为机器代码时进行任何这些假设,并确保所有这些特定操作都严格按程序员编写的方式执行.这对于内存映射设备至关重要,主要是因为处理器不会严格更改内存位置.出于同样的原因,具有共享内存的多处理器系统在公共内存空间上运行时通常需要类似的实践.