在遍历多线程编程的许多资源时,通常会提到volatile说明符。显然,使用此关键字不是在C / C ++和Java(1.4版及更低版本)中至少实现多个线程之间同步的可靠方法。维基百科列出了此说明符的典型用法(未解释如何):
我可以开始在上面列出的用法中看到该说明符的角色,但是由于我还没有对这些领域的完整了解,因此我无法弄清楚该说明符在每种用法中的表现。
有人可以解释吗?
因为您对这些用例感兴趣,所以我将解释第一个。请注意,这是从ac / c 的角度应用的,不确定我如何在Java中发挥作用,尽管我通常怀疑c / c 中的volatile和Java用于完全不同的情况。
内存映射的设备是处理器以与内存相同的方式而不是通过专用总线与之通信的外围设备。
假设您有一个带有映射的计时器的指示灯。通过向其内存地址写入1来打开照明灯,并且其内部计时器递减计数5秒钟并关闭照明灯并将存储位置重置为0。现在,您正在开发一个需要在某些事件后打开照明灯的ac程序。 ,有时在计数器到期之前将其关闭。如果使用常规变量(倾向于作为此类应用程序的指针或引用)写入其内存位置,则由于编译器的优化,可能会出错。
如果您没有使用那么多的变量,并且在关闭照明后不久就打开了灯,并且没有其他任何使用该值的变量- 有时编译器将完全摆脱第一个赋值,否则它将只需将值保存在处理器寄存器中,而无需写入内存。在这两种情况下,光源始终不会打开,因为它的内存从未更改。
现在考虑另一种情况,您需要检查指示灯的状态并点亮。在此,该值从设备的存储器中提取并保存在处理器寄存器中。现在,几秒钟后,灯会自动熄灭。此后不久,您尝试再次打开该灯,但是由于您读取了该内存地址并且此后未进行任何更改,因此编译器假定该值仍为1,因此从不对其进行更改,尽管现在实际上为0。
通过使用易失性关键字,可以防止编译器在将代码转换为机器代码时做出任何这些假设,并确保所有这些特定操作均严格按照程序员的编写来执行。这对于内存映射设备至关重要,主要是因为处理器未严格更改内存位置。由于这些相同的原因,具有共享内存的多处理器系统在公共内存空间上运行时通常需要类似的做法。