volatile在线程同步的作用

引言:近期在家通过《Java核心技术》学习Java基础,遇到了一些理解不了并且在书里找不到答案的问题,于是想通过博客记录并且复现这些问题。希望可以给大家带来帮助。这也是我写的第一篇博客,如果有错误的话,欢迎大家指正。

JVM在运行时候如何分配内存

首先我想介绍一下Java虚拟机(JVM)在运行时候内存分配的问题,这有助于理解volatile在线程同步的作用。Java内存模型将内存分为主内存和工作内存,每个线程都有自己的工作内存。每次线程读到主内存的变量时,会读取一次主内存的变量,并在自己的工作内存形成该变量的拷贝。当该线程使用到某个变量时,它修改的是自己工作内存中的变量而非主内存的变量。在某些时刻,线程会将工作内存的值更新到主内存中。

volatile的初步理解

我们先来看一个例子

public class VolatileDemo {
	static boolean a=false;
 	static class myThread extends Thread{
  		public void run() {
			while(a==false) {
  		 		continue;
   			}
  		}
 	}
 	public static void main(String[] args) {
  		Thread thread=new myThread();
  		thread.start();
 	 	try {
 			  Thread.sleep(1000);
  		}
 	 	catch(Exception e) {}    //让主线程休眠的目的是防止子线程myThread在拷贝到自己的工作内存前就已经将a修改为true
  		a=true;
 	}
}

这个线程的运行过程是怎样的呢?当主线程将a修改为true后,thread线程就跳出while循环,然后程序结束吗? 结果并不是这样的,程序会一直运行下去不会终止。

把前面介绍的JVM在运行时分配内存的方式应用到该例子上来:当thread线程运行到在这里插入图片描述的时候,就会将变量a拷贝到自己的工作线程中,之后的循环条件判断也是取工作线程中的a变量。后面虽然主线程在自己的工作内存中将a修改为true并更新到主线程中(如果修改工作内存中的变量就会更新主内存对应的值),但是thread线程还是没有重新“拿取”更新后的a变量,所以始终跳不出在这里插入图片描述这个循环,程序也就一直运行着。

 static volatile boolean a=false;

那么volatile这个关键字的作用是什么呢?
它的作用就是把强制线程每次读取到a变量时,都是从主内存中取值。这样一来,当主线程修改a后,thread线程读取到a的值也是true。程序就会终止。

volatile的作用

  1. 确保改变量对所有线程的可见性:线程每次读取到volatile修饰的变量时,都是直接从主内存取值。而普通变量则是读取自己的工作内存,所有大多时候当其他线程修改某个普通变量后,另外一个线程一直读取的是没有修改后的值。
  2. 禁止指令重排序优化。这个作用由于涉及到比较底层的部分,我还没能理解。如果有小伙伴知道,希望能向你请教。

volatile不能确保原子性

a+=1这样的语句并不是原子操作。该语句可能被拆解为

  1. 将a加载到寄存器
  2. 增加1
  3. 将结果写为a
    上面这些指令才是原子操作。
    我们这里先假设a=0并且a被volatile修饰,如果线程1执行a+=1时,线程2执行b=a,那么不能确保b的值等于1。而是可能为0,也可能为1。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值