volatile

volatile:是java虚拟机提供的轻量级同步机制。
volatile三大特性:保证可见性、不保证原子性、禁止指令重排。
JMM三大特性:可见性、原子性、有序性。

JMM(Java Memory Mode java内存模型):由于jvm运行程序的实体是线程,而每个线程创建时jvm都会为其创建工作内存(有些地方称为栈内存),工作空间是每个线程私有的数据区域,而java内存模型规定所有的变量都保存在主物理内存中,主内存是共享内存区域,所有线程都可以访问,但线程对变量的操作(读写赋值等)都要在工作内存中进行,首先要将变量从主内存中拷贝到工作内存,然后对变量进行操作,操作完成后再把变量写回到主内存中,不能直接操作主内存中的变量。不同线程不能访问对方工作内存中的变量,线程中的通信(传值)必须通过主物理内存。

可见性:每个线程从主物理内存里读取变量age:16,t1线程对age变量进行修改,然后将修改结果age:18返回主物理内存,然后修改后的消息第一时间分享给其他线程的机制称为JMM(java内存模型)的可见性。

不保证原子性的原因:例如多个线程进行n++操作,t1线程读取主物理内存中的值为0,然后进行加一操作后为1,接着写回到主物理内存的过程中线程被挂起了,t2线程也进行同样的操作后主物理内存中的值为1,此时t1线程继续将1写到主物理内存,此时发生写数据丢失。

指令重排:计算机在执行程序时,编译器和处理器为了提高效率常常会对指令进行重排,一般分为三步:
源代码–>编译器优化指令的重排–>并行指令的重排–>内存系统的指令重排–>最终的执行指令
单线程环境确保优化指令重排的执行结果和顺序执行代码结果一致;
处理器在执行重排时要保证指令之间的依赖性;
多线程环境下线程交替执行,由于编译器优化指令重排的原因,线程之间使用的同一变量的一致性无法保证,结果无法预测。

public mySort(){
	int x=1;  //语句1
	int y=2; //语句2
	x=x+1; //语句3
	y=y+1; //语句4
}

执行顺序有1234、2134、1324、2413

volatile禁止指令重排的原因举例:

class ResortDemo{
	int i=0;
	boolean b=flase;
	public method1(){
		i=1;		//语句1
		b=true;		//语句2
	}
	public method2(){
		if(b){
			i+=5;	//语句3
			System.out.println(i);
		}
	}
}

由于多线程环境中存在指令重排,语句2可能会排在语句1的前面,从而输出5,为了消除这种可能我们在定义b变量时在前面使用volatile修饰。
volatile实现禁止指令重排,从而避免多线程环境下程序出现乱序执行的情况。
vola写操作在这里插入图片描述内存屏障(Memory Barrier),又叫内存栅栏,是一个cpu指令,它的作用有两个:
1.保证特定操作的执行顺序
2.保证某些内存的可见性(利用该特征实现volatile内存可见性)
由于编译器和处理器都能执行指令优化重排,如果在指令间插入一条内存屏障则会告诉编译器和cpu,不管什么指令都不能和这条内存屏障重排序,也就是说通过插入内存屏障可以禁止在屏障前后指令重排序优化。内存屏障另一个作用是强制刷出各种cpu的缓存数据,从而在任何cpu线程上都可以读到这些数据的最新版本。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值