| 定义 |
当在声明值类型字段时使用 volatile 修饰符,就称该字段为易失字段。
例如:public vollatile int counter = 0;
| 背景 |
为了加快CPU处理速度,编译器会对指令进行优化,将变量值在寄存器中缓存,下一次使用时就直接读取这个缓存而不是内存,
单线程应用程序受益于这个技术,在确保正确运行的前提下提高了运行速度;但是在多线程应用程序中,则可能由于这个CPU优
化技术导致从缓存中读取的是脏数据,从而导致应用程序Bug。
| 示例 |
class Demo
{
public int counter = 0;
}
Demo obj = new Demo();
我们假设这个Demo类的实例obj会被多个线程进行读写操作,又由于达到了编译器的优化条件,每个线程都会在寄存器中缓存一个
obj中的公开字段counter的副本。
这时,线程A修改了counter,线程B又对counter进行了读或写,但B仍使用的是最初counter的值,无法读取到counter的最新值,
因为每个线程读取的来源和更改的目标都是自己缓存下了的那个值。
这样Bug便产生了。
| 解决 |
使用 volatile 修饰符能够保证该字段不被缓存到CPU寄存器中,从而每个线程都能够对这个字段的实际内存进行“即时”的读写:
一个线程对易失字段做了更改,便会立即反映到该字段的实际内存地址中,而其他线程对易失字段进行读取的时候,也是直接从该
字段的实际内存地址中获取值的。
换句话说,任何线程中改变了易失字段的值,所有其他线程立即获取到了其最新值。
我们在多线程应用程序开发中,千万不要忘记在能被多个线程共享的值类型变量前面加上个vollatile修饰符啊!
浙公网安备 33010602011771号