结合JMM聊聊volatile的功能

今天聊volatile关键字,定义:volatile修饰的实例变量(instance variable---类加载阶段将symbolic reference转为district reference 并保存到 method area)在线程内部每次使用都强制从工作内存中读取值。

edited at 2019 03.12 23:37---------------------------------------------------------------------------------------------------------------------------

volatile 变量在写操作的时候执行了lock指令,而lock指令所作的三件事情:

1、将volatile变量(就用countNumber)从工作内存保存到主内存中,即从frame中刷到了heap中,

2、将其他用到这个变量的地方的缓存清除(缓存一致性)

3、禁止指令重排序

参考:

此文 的volatile部分

《java并发编程的艺术》2.1节 volatile的应用

---------------------------------------------------------------------------------------------------------------------------------------------------------------

class Thread1 extends Thread{
    volatile public static boolean flag=true;

    public void setFlag(boolean flag){
      this.flag = flag;
    }

    public void run(){
      print("start thread");
      while(flag){
      }
      print("flag is false now,end thread");
    }
}
class demo{
    main{
       Thread1 t = new Thread1();--------------------------1
       t.start();
       t.setFlag(false);-----------------------------------3
       print("main set flag false");
    }
}

步骤1:在heap中保存一个Thread1的实例,t(t保存在vm stack)保存该实例heap中首地址。

执行t.start() (对java中线程实现还没深入),从vm stack 分配内存给执行方法(一般方法执行的stack分配多大已经在编译时期就确定了),这里分配的叫frame,frame中保存了local variable,所属方法在run-time constant pool中的引用,操作栈(类似CPU中的ALU,负责运算),返回地址。那么这里的私有内存就是在操作栈(operand stack),也就是线程私有stack。如果不加volatile,那么运行的flag永远不会被读取到false,即使main线程已经将instance variable设置成了false(步骤3),加了volatile,就是强制在判断执行前,插入一个指令,从heap中读取flag值并更新到operand stack中。这就是volatile的可见性。但是并不能保证原子性。也就是不能保证同步。这里更正一下,对volatile修饰的变量的单个操作满足原子性,但是复合操作不满足原子性。可以参看此文,原子性的保证通过两种方式:

1:确定可以修改该实例变量的方法有几个。对这几个方法进行class锁,不是instance 锁。

2:如果是很多途径可以修改这个变量,那就要原子类。

附上图片易于理解

自己的理解。有不对的地方请指正。

参考:

《java多线程编程核心技术》(第二章volatile部分)---高洪岩

《深入理解java虚拟机》---周志明

java virtual specification

《java concurrency in practice》---Brian Goetz
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值