1.volatile关键字的作用和原理
答:java允许线程访问共享变量,为了确保共享变量能被准确和一致的更新,线程应该确保通过排他锁单独获取这个变量。volatile就是用来保证在线程之间的可见性(保存内存可见性(memory Visibility)变量随时见到的都是最新值),还有防止指令重排序。
原理:
(1)可见性:这里涉及到java变量的读写,从jvm层中我们知道,共享变量存放在java堆(主内存)中,当某一个线程需要使用该变量需要完成以下几步操作:(工作内存,具体某一个线程执行时的占用的内存)
a.lock:作用于主内存,把内存标示为线程独占状态。
b.unlock:作用于主内存,解除独占状态。
c.read:作用于主内存,把一个变量的值从主内存传输到线程的工作内存。
d:load:作用于工作内存,把read操作传过来的变量值放入工作内存的变量副本中。
e:use: 作用于工作内存,把工作内存中的一个变量值传给执行引擎。
f:asign:作用于工作内存,把一个从执行引擎接收到的值赋值给工作内存的变量。
h:store:作用于工作内存,把工作内存的一个变量的值传给主内存中。
i: write:作用于主内存的变量,把store操作的变量的值放入主内存的变量中。
volatile的特殊规则就是:
read,load,use动作必须连续出现。
assign,store,write动作必须连续出现。
所以,使用volatile修饰变量能够保证:每次读取前必须先从主内存刷新最新的值,每次写入后必须立即同步会主内存当中。
(2)指令排重原理
这里涉及到基于偏序关系的Happens-Before内存模型;简单来讲volatile关键字通过“内存屏障”来防止指令被重排序,为了实现volatile的内存语义,编译器在生成字节码时,会在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序,下面是基于保守策略的jMM内存屏障插入策略:
在每个volatile写操作的前面插入一个StoreStore屏障,在每个volatile写操作的后面插入一个StroreLoad屏障,在每一个volatile读操作的后面插入一个LoadLoad屏障,在每一个volatile读操作的后面插入一个LoadStore屏障。
2.原子操作类和cas
......待续,之后继续完善