Java volatile keyword

前言:

用在多线程,同步变量。线程为了提高效率,将某个成员(A)变量拷贝了一份(B)。线程中对A的訪问事实上訪问的是B。仅仅在某些动作时才进行A和B的同步。因此存在A和B不

一致的情况。volatile就是用来避免这个中情况的。volatile告诉jvm,它所修饰的变量不保留拷贝,直接訪问主内存中的A。

在Java内存模型中,有main memory,每一个线程也

有自己的memory(寄存器).为了性能,一个线程会在自己的memory中保持要訪问的变量的副本。

这样就会出现同一个变量在某个瞬时,在一个线程的memory中的值可能与另

一个线程memory中的值,或者main memory中的值不一致的情况。

一个变量声明为volatile,就意味着这个变量是随时会被其它线程改动的。因此不能将它cache在线程memory中。

1.特性:

volatilekeyword确保了应用中的可视性。假设你将一个域声明为volatile,那么仅仅要这个域产生了写操作,那么全部的读操作都能够看到这个改动。

2. 原子性:

volatile修饰的变量不同意线程内部缓存和重排序。即直接改动内存。所以对其它线程是可见的。但volatile仅仅能让被它修饰的内容具有可见性,但不能保证它具有原子性。

仅仅会影响可见性,不会影响原子性。

3.其它:

1) 保证了不同线程对这个变量进行操作时的可见性,即一个线程改动了某个变量的值,这新值对其它线程来说是马上可见的。

  2) 禁止进行指令重排序。

4.实现机制:

观察增加volatilekeyword和没有增加volatilekeyword时所生成的汇编代码发现,增加volatilekeyword时,会多出一个lock前缀指令。lock前缀指令实际上相当于一个内存屏障(也

称内存栅栏)。内存屏障会提供三个功能:

1) 它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在运行到内存屏障这句指令时。在它前面的操作已全

部完毕。

2) 它会强制将对缓存的改动操作马上写入主存。

3) 假设是写操作。它会导致其它CPU中相应的缓存行无效。

5.通常volatile必须具备下面两个条件:

1) 对变量的写操作不依赖于当前值。

2) 该变量没有包括在具有其它变量的不变式中。

posted @ 2017-06-30 15:48  yfceshi  阅读(151)  评论(0编辑  收藏  举报