volatile的实现原理

java中的并发机制依赖于JVM的实现和CPU的指令。java并发机制包括volatile,synchronized和原子操作。本文将探索volatile的底层实现原理。

在并发编程中synchronized和volatile都扮演着重要的角色,volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的可见性。可见性是指,一个线程修改共享变量时,另外一个线程能读到这个修改的值。volatile变量修饰符如果使用恰当,会比synchronized效率更高,因为它不会引起线程上下文切换和调度。

如果一个字段被声明称volatile,那么java线程内存模型会确保所有的线程看到这个变量的值是一致的。

volatile在硬件层面上的是如何保证共享变量的可见性的?

为了提高处理速度,cpu一般不和内存直接交互,而是将内存中的数据读到缓存里,然后再进行操作,操作完了不知道何时会写回到内存中。当对一个volatile修饰的共享变量进行写操作时,JVM就会向处理器发送一条Lock前缀指令,将这个变量所在的缓存行写回到内存中。但是,就算写回到内存,其他处理器的缓存中保存的数据仍然是旧的。所以在多处理器下,为了保证各个处理器的缓存是一致的,就会实现一套缓存一致性协议:每个处理器通过嗅探在总线上传播的数据来检查自身缓存的值是否过期,当处理器发现自己缓存行对应的内存地址被修改,就会将当前缓存行设置成无效。当处理器再次对这个数据进行修改时,会重新从系统内存中把数据读到处理器缓存中。

volatile的两条实现原则:

  1. Lock前缀指令会引起处理器缓存回写到内存。