-
在java的内存模型中有区分为主内存和工作内存,Java内存模型规定所有变量存储在主内存中,每条线程都有自己的工作内存。
而主内存和工作内存之间的交互分为8个原子操作分别是lock,unlock,read,load,assign,use,store,write。
“lock(锁定):作用于主内存的变量,它把一个变量标识为一条线程独占的状态。
unlock(解锁):作用于主内存的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
read(读取):作用于主内存的变量,它把一个变量的值从主内存传输到线程的工作内存中,以便随后的load动作使用。”
“load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中。
use(使用):作用于工作内存的变量,它把工作内存中一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用到变量的值的字节码指令时将会执行这个操作。
assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收到的值赋给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。
store(存储):作用于工作内存的变量,它把工作内存中一个变量的值传送到主内存中,以便随后的write操作使用。
write(写入):作用于主内存的变量,它把store操作从工作内存中得到的变量的值放入主内存的变量中。”
有了上面的知识,我们现在就可以解释为什么Volatile关键字能让变量有可见性。
int volatile a = 0;
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
a++;
}
});
thread.start();
上面代码中 a是一个volatile变量
那么在新的线程中执行a++;java虚拟机规定:
- 只有对a的操作动作是load时,下一个执行的动作才可以是use,这两个互为充分必要条件。(这个就可以保证每次对a的操作都是主内存最新的值);
- 只有上一个对a的操作是assign时,下一个动作才可以是load,这两个条件互为充分必要条件,(这个条件可以保证在工作内存操作a,都会同步到主内存);
有了上面的两个条件就可以保证a的可见性了。