Java多线程——Volatile

Volatile的英文意思是 易挥发的/易变的,一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么它就具备了两层语义:

  • 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。(与JVM内存模型有关,注意区分和Static的区别)

  • 禁止进行指令重排序。


1.可见性:

//线程1
boolean flag = false;
while(!flag){
    doSomething();
}

//线程2
flag = true;

这段代码不一定会将线程中断,也许在大多数时候,这个代码能够把线程中断,但是也有可能会导致无法中断线程(虽然这个可能性很小,但是只要一旦发生这种情况就会造成死循环了)。为了防止这类问题(退出线程常用到volatile),用volatile修饰flag来保证其可见性。


2.禁止JVM进行指令重排序:

/线程1:
context = loadContext();   //语句1
inited = true;             //语句2
 
//线程2:
while(!inited ){
  sleep()
}
doSomethingwithconfig(context);

由于JVM的重排序,可能语句2会在语句1之前执行,那么久可能导致context还没被初始化,而线程2中就使用未初始化的context去进行操作,导致程序出错。

这里如果用volatile关键字对inited变量进行修饰,就不会出现这种问题了,因为当执行到语句2时,必定能保证context已经初始化完毕。


场景:单例(双重检测)

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;
    }
}

转载于:https://my.oschina.net/u/4120078/blog/3043368

你可能感兴趣的:(java)