JMM

简介

定义

**JMM(JAVA内存模型)**本身是一种抽象的概念,并不真实存在,它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式

运行过程

  1. JVM运行程序的实体是线程,而每个线程创建时JVM都会为其创建一个工作内存(栈空间),工作内存是每个现成的私有数据区域
  2. Java内存模型中规定所有变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问
  3. 线程对变量的操作(读取赋值)必须在工作内存中进行,首先要将变量从主内存拷贝到线程自己的工作内存空间,然后对变量进行操作,操作完成后再将变量写回主内存
  4. 不能直接操作主内存中的变量,各个线程中的工作内存中存储着主内存中的变量副本拷贝,因此不同的线程间无法访问对方的工作内存,线程间的通信(传值)必须通过主内存来完成

在这里插入图片描述

三特征

参考:

  1. 参考1
  2. 参考2

原子性

  1. 定义
    原子性操作就是指这些操作是不可中断的,要做一定做完,要么就没有执行,也就是不可被中断。
  2. 例子
    在这里插入图片描述
  3. 解决:在java中提供了两个高级的字节码指令monitorenter和monitorexit,使用对应的关键字Synchronized来保证代码块内的操作是原子的

可见性

  1. 定义
    可见性是指当一个线程修改了某一个共享变量的值,其他线程是否能够立即知道这个修改
  2. 解决方法
    • Java中可以使用volatile关键字来保证多线程操作时变量的可见性
    • volatile的功能是被其修饰的变量在被修改后可以立即同步到主内存,而被其修饰的变量在每次使用之前都会从主内存刷新
    • 除此之外,synchronized和final两个关键字也可以实现可见性 。volatile也可以看作是轻量级的锁,在其内部使用了Lock指令来解决可见性问题

有序性

  1. 定义
    JMM是允许编译器和处理器对指令重排序的,但是规定了 as-if-serial语义,即不管怎么重排序,程序的执行结果不能改变
  2. 多线程出错例子
/*
      如果这个类的writer()和reader()方法是在不同的线程中运行的。
      那么writer()中的方法可能会被重排序为flag= true先执行。
      这个时候如果被中断,换到执行reader()的线程执行,flag为true,进入if判断就会自然认为a = 1;
      但是这个时候a还是0。这里大概就能理解重排序带来的问题了
 */

class OrderExample{
    int a = 0;
    boolean flag = false;
    public void writer(){
        a = 1;
        flag = true;
    }

    public void reader(){
        if(flag){
            int i = a + 1;
        }
    }
  1. 解决方法:
    在Java中,可以使用synchronized和volatile来保证多线程之间操作的有序性。只是实现方式有所区别: volatile关键字会禁止指令重排,synchronized关键字保证同一时刻只允许一个线程的操作
  2. 解决例子
/*
    使用volatile来标示flag,就能解决上面说到的可见性问题
    这种对变量的读写操作,标记为 volatile可以保证修改对线程立刻可见
    比 synchronized, Lock有一定的效率提升
 */
class OrderExample{
    int a = 0;
    volatile boolean flag = false;
    public void writer(){
        a = 1;
        flag = true;
    }

    public void reader(){
        if(flag){
            int i = a + 1;
        }
    }
}

JMM数据原子操作

  1. read(读取):从主内存读取数据(还未写入工作内存)
  2. load(载入):将主内存读取到的数据写入工作内存
  3. use(使用):从工作内存读取数据来计算
  4. assign(赋值):将计算好的值重新赋值到工作内存中
  5. store(存储):将工作内存数据写入主内存(还未写入主内存)
  6. write(写入):将store过去的变量值赋值给主内存中的变量
  7. lock(锁定):将主内存变量加锁,标识为线程独占状态
  8. unlock(解锁):将主内存变量解锁,解锁后其他线程可以锁定该变量
    在这里插入图片描述

read和load store和write 必须成对出现

AA

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值