Java并发编程原理-内存模型

基本概念

程序

代码,完成某一任务的代码序列(静态的概念)

进程

程序在某些数据上的一次运行,有开始、有结束、有生命周期(动态的概念)

线程

一个进程包含一个或多个线程,占有该资源(内存、CPU等)的独立单元(微观的概念)

JVM与线程

JVM什么时候启动 :Java程序类被调用的时候,JVM线程会启动,然后再启动其他线程(如:main)

JVM内存区域

JVM内存区域是人为划分的区域,实际的物理区域并不会如此划分的。
Java内存区域

  1. 方法区:类信息、常量、static、JIT(即时编译) ,如常用的反射加载。(信息共享)
  2. 堆区域:实例对象 GC(垃圾回收)工作的主要对象。(信息共享、OOM内存溢出)
  3. VM stack(栈):Java方法运行的内存模型(OOM内存溢出)。如下:
    VM stack
  4. PC:Java线程的私有数据,这个数据就是执行下一条指令的地址。
  5. native method stack:线程私有的区域 ,与虚拟机 jvm的native方法有关,一般情况下我们编码开发过程中是不关心。

JVM内存模型

Java Memory Model(JMM),是一种规范,是一种抽象的模型。
JMM

  1. 主内存:共享的信息
  2. 工作内存:私有信息,如果是基本数据类型,直接分配到工作内存;如果是引用的地址,存放在工作内存;如果是引用的对象,那么存放在堆中
  3. 工作方式:
    A)线程修改私有数据,直接在工作空间修改
    B)线程修改共享数据,把数据复制到工作空间中去,在工作空间中修改,修改完成以后,刷新内存中的数据。有可能存在线程不安全(不一致性)

其中,JVM内存区域划分就是根据JVM的内存模型(JMM)来进行实现的。JMM是模型,JVM内存区域是实现方案。工作内存对应的VM Stack,存储私有信息,方法区和堆对应的主内存,可以进行信息共享。

硬件内存架构与Java内存模型

  1. 硬件架构
    硬件架构
    • CPU缓存的一致性问题:并发处理的不同步,如内存中的变量X=1,CPU1修改X=2,此时CPU2读取X的值,那么CPU2读取的X的值有可能为1(由于并发处理,此时Cache中的2还未同步到内存中),也有可能为2.
    • 解决方案:
      • 总线(BUS)加锁、 降低CPU的吞吐量,但也降低了CPU的处理能力
      • 缓存上的一致性协议(MESI)
        当CPU在Cache中操作数据时,如果该数据是共享变量,数据在CACHE读到寄存器中,进行新修改,并更新内存数据
        CacheLINE(信号线)置无效,其他的CPU就不从Cache中读取,而从内存中去读数据。
  2. Java线程与硬件处理器
    在这里插入图片描述
  3. Java内存模型与硬件内存架构的关系
    内存模型与硬件内存架构的关系

由上可知,交叉访问,导致数据不一致性。
4. Java内存模型的必要性
Java内存模型的作用:规范内存数据和工作空间数据的交互

并发编程的三个重要特性

  1. 原子性:不可分割 ,如转账操作,扣钱和加钱,要么同时成功,要么同时失败。再如给x赋值为1,x=1,那么也为原子性。
  2. 可见性:线程只能操作自己工作空间中的数据,不能操作其他工作空间的数据。操作内存中数据的时候,需要首先将内存中的数据读取到自己的工作空间后进行操作。
  3. 有序性:但程序中的顺序不一定就是执行的顺序,如以下代码的执行顺序不一定按照编写顺序进行执行,会对程序进行重排,目的是为了优化代码,提高执行效率。
    int x = 1;
    int y = 2;
    int z = 3;
    z = x + y;
    System.out.println("hello");
    int m = 0;
    

关于重排,主要有2种:编译重排、指令重排
重排的原则:

  • as-if-seria:不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不会改变。编译器和处理器不会对存在数据依赖关系的操作做重排序,因为这种重排序会改变执行结果。但是,如果操作之间不存在数据依赖关系,这些操作就可能被编译器和处理器重排序。如上述代码,在不影响结果的情况下,CPU会优先执行耗时较少的读操作,然后再执行写操作。先执行x=1,y=2,z=3,m=0,然后再执行z=x+y。
  • 如果一个操作执行的结果需要对另一个操作可见,那么这2个操作之间必须要存在happens-before关系。两个操作之间具有happens-before关系,并不意味着前一个操作必须要在后一个操作之前执行!happens-before仅仅要求前一个操作(执行的结果)对后一个操作可见,且前一个操作按顺序排在第二个操作之前。

JMM对三个特征的保证

JMM与原子性

如果是私有数据具有原子性,如果是共享数据没原子性(读写)

  • X=10 是一种写操作, 具有原子性不可分割
  • Y=X 没有原子性(分2步执行)
    1. 把数据X读到工作空间(原子性)
    2. 把X的值写到Y(原子性)
  • i++ 没有原子性
    1. 读i到工作空间
    2. +1;
    3. 刷新结果到内存
  • Z=Z+1 没有原子性
    1. 读z到工作空间
    2. +1;
    3. 刷新结果到内存

结论:多个原子性的操作合并到一起没有原子性
保证方式:

  • Synchronized
  • JUC Lock的lock
JMM与可见性
  • Volatile:在JMM模型上实现MESI协议
  • Synchronized:加锁
  • JUC Lock的lock
JMM与有序性
  • Volatile:位置不变
  • Synchronize:封锁,位置不变
  • Happens-before原则:
    1. 程序次序原则
    2. 锁定原则 :后一次加锁必须等前一次解锁
    3. Volatile原则:霸道原则
    4. 传递原则:A—B —C A–C
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值