java volatile关键字使用

1、为什么要使用volatile关键字?

先看下面的代码:

//线程1
boolean stop = false;
while(!stop){
    doSomething();
}
 
//线程2
stop = true;

事实上,这段代码会完全运行正确么?即一定会将线程中断么?不一定。

解释:

        每个线程在运行过程中都有自己的工作内存,那么线程1在运行的时候,会将stop变量的值拷贝一份放在自己的工作内存当中。

        那么当线程2更改了stop变量的值之后,但是还没来得及写入主存当中,线程2转去做其他事情了,那么线程1由于不知道线程2对stop变量的更改,因此还会一直循环下去。

        为了解决这种问题,引入volatile关键字;

2、volatile关键字使用的特点:

1、使用volatile关键字会强制将修改的值立即写入主存。

2、使用volatile关键字的话,当线程2进行修改时,会导致线程1的工作内存中缓存变量stop的缓存行无效。

3、由于线程1的工作内存中缓存变量stop的缓存行无效,所以线程1再次读取变量stop的值时会去主存读取。

4、不能保证原子性只保证的是可见性、能保证有序性。

5、由于有些时候对 volatile的操作,不会被保存,说明不会造成阻塞。不可用与多线程环境下的计数器。

原子性测试:

package thread;
public class Test {
    public volatile int inc = 0;
 
    public void increase() {
        inc++;
    }
 
    public static void main(String[] args) {
        final Test test = new Test();
        for(int i=0;i<10;i++){
            new Thread(){
                public void run() {
                    for(int j=0;j<1000;j++)
                        test.increase();
                };
            }.start();
        }
 
        while(Thread.activeCount()>1)  //保证前面的线程都执行完
            Thread.yield();
        System.out.println(test.inc);
    }
}

结果:

值总是小于10000;即可说明其不满足原子性。

有序性解释:

a=0;//1
b=100;//2
falg=true;//3
c=20;//4
d=39;//5
e=49;//6

falg是volatile变量,其余变量不是;

这段程序能够保证,3在其执行前,1,2均执行完,但1,2二者执行顺序如何,3不能保证。

4,5,6执行前,3一定执行完,且3之前的所有结果对3以后的代码可见,至于4,5,6的执行顺序如何,3保证不了。

可见性的理解:

当对一个volatile变量进行写操作的时候,JMM会把该线程对应的本地内存中的共享变量的值刷新到主内存中。
当读一个volatile变量的时候,JMM会把该线程对应的本地内存设置为无效,要求线程从主内存中读取数据。

 3、何时使用volatile关键子

1、作状态标记量

volatile boolean inited = false;
//线程1:
context = loadContext();  
inited = true;            
 
//线程2:
while(!inited ){
sleep()
}
doSomethingwithconfig(context);
volatile boolean flag = false;
 
while(!flag){
    doSomething();
}
 
public void setFlag() {
    flag = true;
}

2、double check

class Singleton{
    private volatile static Singleton instance = null;
 
    private Singleton() {
 
    }
 
    public static Singleton getInstance() {
        if(instance==null) {
            synchronized (Singleton.class) {
                if(instance==null)
                    instance = new Singleton();
            }
        }
        return instance;
    }
}

猜你喜欢

转载自blog.csdn.net/cincoutcin/article/details/80315522