java内存模型,可以理解为变量的访问规则,在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节。
线程、主内存、工作内存的交互关系如下:
8种内存交互操作:
lock:
unlock:
read:
load:
use:
assign:
store:
write:
volatile关键字作用
1可见性:保证变量对所有线程可见
普通变量的值在线程间传递均需要通过主内存完成,volatile变量也是如此。例如线程A修改一个普通变量的值,然后向主内存进行回写,另外一条线程B在线程A回写完成之后再从主内存进行读取操作,新变量值才会对线程B可见。volatile的特殊规则保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新。volatile变量对所有线程是立即可见的(在各个线程的工作内存中,volatile变量也可以存在不一致的情况,但每次使用之前都要先刷新,执行引擎看不到不一致的情况,因此可以认为不存在不一致的问题)
2非原子性
package extthread;
public class MyThread extends Thread{
public static int count;
private static void addCount(){
for(int i=0;i<100;i++){
count++;
}
System.out.println("count="+count);
}
@Override
public void run(){
addCount();
}
}
package extthread;
public class Run {
public static void main(String[] args){
MyThread[] mythreadArray=new MyThread[100];
for(int i=0;i<100;i++){
mythreadArray[i]=new MyThread();
}
for(int i=0;i<100;i++){
mythreadArray[i].start();
}
}
}
打印结果:count=9137
原因:表达式i++的操作步骤:
1)从内存中取出i的值
2)计算i的值
3)将i的值写到内存中
假如某一线程在第2步计算值的时候,另一个线程也修改了i的值,这个时候就会出现脏读数据的情况,解决办法是使用synchronized关键字修饰。volatile本身并不处理数据的原子性,只是强制对数据的读写及时影响到主内存。
3禁止指令重排序优化