1.定义:用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最的值。 2.语义: 第一:保证线程之间变量的可见性。简单地说就是当线程A对变量X进行修改后,在线程A后执行的其他线程能看到变量X的变化。更纤细的说是符合两个规则: *线程对变量进行修改之后,要立刻写到主内存。 *线程对变量读取的时候,要从主内存中读,而不是缓存。
有关线程执行过程中住内存和缓存,可以进行如下解释。
JAVA 为了保证其平台型,使JAVA应用程序和操作系统内存模型隔离开,需要定义自己的内存模型。在java内存模型中,内存分为主内存和工作内存两个部分,其中主内存是所有线程所共享的,而工作内存则是每个线程分配一份,各线程的工作内存彼此独立,互补课件,在线程启动的时候,虚拟机为每个内存分配一块工作内存,不仅包含了线程内部定义的局部变量,也包含了线程所需要使用的共享变量(非线程内构造对象)的副本,即为了提高执行效率,读取副本比直接读取主内存更快(这里可以简单地将主内存理解为虚拟机中的堆,而工作内存理解为栈) 对于共享普通变量来说,约定了变量在工作内存中发生变化之后,必须要回写到工作内存(迟早要回写,并不是马上回写),但对于volatile修饰的变量,则要求在工作内存中发生变化之后,必须马上回写到工作内存(之所以是工作内存是因为,原来的变化是在工作内存的副本中进行),而线程读取volatile变量的时候,必须马上到工作内存中去取最新值,而不是读取本地工作内存的副本,此规则保证了前面所说的“当线程A对变量X进行修改后,在线程A后面执行的其他线程能看到变量X的变动。” 工作内存副本变动-工作内存变动-新的线程读取主内存的时候共有变量的值已经变化为最新值。
重点详解:工作内存可以说是内存的一份缓存,为了避免缓存的不一致性,所以volatile需要废弃此缓存,但除了内存缓存之外,在CPU硬件级别也是有缓存的,即寄存器。加入线程A将变量X由0修改为1的时候,CPU是在其缓存内操作,没有及时回写到内存,那么JVM是无法X=1是能及时被之后执行的线程B看到的。而JVM在处理volatile变量的时候,也同样用了硬件级别的缓存一致性原则。 第二:禁止指令重排序。如同我们在另一片博客《懒汉式和饿汉式》中所用到的一致。