在讲解volatile关键字之前,我们先来看看操作系统中缓存一致性的概念。
众所周知,cpu的运行速度是远高于主存的读写速度的,在运行过程中,为了交换数据,cpu必须频繁的进行数据的读写操作,主存读写速度慢造成了cpu运行的吞吐量减少。为了解决这一问题,现在的机器都会在添加一层高速缓存(其实不止一层,有多层).以后每次cpu进行读写操作时,都直接和高速缓存交互,之后在将高速缓存中的数据回刷到主存中。在单线程情况下这没有任何问题,但在多线程环境下这会带来一些隐患。因为这会造成每个线程更改了自己高速缓存中的数据时(即使将这个更改的数据从缓存中刷回主存),其他变量读取的仍是最开始的自己高速缓存中的数据,这就造成了数据的不可见性。为了预防数据不可见性,在硬件方面有一个缓存一致性协议协议。其中最出名的MESI协议。
缓存一致性协议(MESI):
当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存行置为无效状态,因此当其他CPU需要读取这个变量时, 发现自己缓存中缓存该变量的缓存行是无效的,那么它就会从内存重新读。
在jvm中,所有变量都存在主存当中,每个线程都有自己的工作内存(也就是前面说的高速cache)。也就是说,当访问一个共享变量时,多个java线程在自己的工作内存中都会有这个共享变量的一份副本。当某个线程更改了自己工作内存中更新了数据时,此时这个线程阻塞了或者其他原因,没有及时将这个更新的数据刷回主存,那么其他线程再从主存或自己的工作缓存中读取的数据还是原来旧值,也就是说,