java voliatile key word

java中的voliatile变量,在java中右有两个语义
1.可见性,每次voliatile变量修改时,都会直接写到主内存中
2.有序性,
1.可见性,
       表现为每次voliatile变量修改时,都会直接写到主内存中,另外每个线程读取voliatile变量时,都会从主内存中读取,但是voliatile变量不能保证变量的安全性,具体原因我们稍后讨论,有人问,voliatile变量怎么保证数据在线程间的可见性,详细的过程如下
在JVM中,为了避免系统以及硬件在内存间的访问差异:JVM提供了自己的内存模型来定义程序中各个变量的访问规则,也就是虚拟机中的变量从存储到内存和从内存中取出变量的底层细节,
这个变量不包括,局部变量和方法参数,因为时线程私有的,不存在竞争的问题,
java的内存模型有三部分组成:线程,工作内存,主内存;
每一个线程有自己的一个工作内存,在线程运行时,会将需要的变量从主内存中copy到工作内存中,如果线程中有对变量的赋值,会先更新工作内存,然后在更新到主内存中;主内存一般是我们说到JVM堆,而工作内存对于虚拟栈中的部分区域(局部变量表,保留引用,但是不会保留内存对象),一般为了运行的效率,JVM会将工作内存放在寄存器和高速缓存中,
在JVM中,工作内存与主内存之间的交互过程,
1.线程读取主内存中的数据,将数据复制到工作内存中(寄存器,高速缓存行)
2.经过线程中的运算复制,改变了数据的值,将数据覆盖本线程的工作内存中,然后再回写到主内存
往往再2的过程中(非原子性操作),因为线程间缺少同步机制的及线程间无序性(从一个线程观察另外一个线程,另外一个线程操作总是无序的,而且无同步机制的情况下,线程之间的调度完全依靠cpu调度器,不能保证线程的执行顺序),引发线程的安全问题,也就是各线程之间的数据相互覆盖,会影响最后的结果,同时,个线程之间的数据也是相互不可见的,因为线程间的工作内存是线程独享的,
但是voliatile 修饰的变量却可以达到线程间数据的可见性,即每一个线程中的数据被更新时,其他线程可以马上看到,这个是因为经过voliatile修饰的变量,再复制操作时,会多加一个“lock”这样的指令,这个指令有两个语义,1.可以更新当前线程的工作内存,并且同时使其他线程的工作内存的数据失效,并同时回写到主内存中,当其他线程再读取这个值时(此值以及存在本线程的工作内存了),回被告知,此值以及过期(内存屏障),会重新去主内存中获取这个值,这样就保证了一个线程的数据修改,可以让其他线程可见,也就是可见性的解释。另外一个语义就是,这个语句后的操作,不能被重排序到这个语句之前,一定程度上可以保证操作的有序性,虽然不是完全意义上的有序。第三个,这个语句前的非voliatile变量操作,也是被当中可见性的操作,让其他线程的数据失效,并会写到主内存中,这个有点屌!!

2.有序性
刚才提到 voliatile 修饰的变量被修改时,后面的操作不能被重排序到 修改操作之前,必须等到 变量修改完成才能,进行后续的操作,这个就是所说的 有序性

猜你喜欢

转载自ludizhang.iteye.com/blog/2336164