JUC 三. JMM内存模型

一. 基础

  1. 先看几个面试题
  1. JMM 与 volatile 之间的关系
  2. JMM有哪些特性(什么是JMM三大特性): 原子性,可见性,有序性
  3. 为什么要有JMM, 主要的作用功能是什么
  4. happens-before先行发生原则是什么
  1. 在CPU上有多级缓存,CPU并不直接运行内存中的数据,而是把内存中的数据读取到缓存中,解决内存的读写速度与CPU读写速度不一致会造成数据不一致的问题
    在这里插入图片描述
  2. JMM: java Memory Model 内存模型, java中提供了内存模型,用来屏蔽各种硬件和操作系统的内存访问差异实现跨平台, 本身是一种抽象的概念,一组约定或规范,通过这组约定规范定义了程序中尤其是多线程下,各个变量的读写访问方式,解决了一个线程对共享变量进行写入修改时,其它线程的可见问题,JMM关机点都是围绕在多线程的原子性,可见性,有序性展开的
  3. JMM三大特性
  1. 原子性: 一个线程操作或多个操作共享数据时,要么全部执行成功,要么都不执行
  2. 可见性: 当多个线程访问同一个变量时,如果一个线程修改了变量的值,其它线程能够立即获取到修改后的值, 若两个线程在不同的cpu,那么线程1改变了i的值还没刷新到主存,线程2又使用了i,那么这个i值肯定还是之前的,线程1对变量的修改线程2没看到这就是可见性问题。
  3. 有序性: 线程执行的顺序按照代码的先后顺序执行,jvm底层为了提高程序运行效率,可能会对代码进行优化,重排序,不能保证语句的执行顺序按照代码的先后顺序执行,只保证程序最终执行结果和按照代码顺序执行的结果是一致的, 重排序对单线程运行不会有影响,而多线程就不一定了(源代码到最终执行可能会经过—> 编译器优化重排—> 指令并行的重排—>内存系统的重排—>最终指令执行)
  1. 在内存模型中,内存分为本地内存(cpu缓存)与主内存,本地底层是线程私有的,主内存中是共享的数据本体,当多线程执行时,首先在主内存中将需要的数据读取到当前线程的本地内存中,当线程在修改数据时首先修改的是本地内存中的数据,修改完毕后,在将本地内存中的数据刷出给共享内存,假设在线程A在本地内存中修改了数据,在还没有将修改的值刷出给主内存的时候,线程B执行读取了主内存中的这个数据,就会造成数据不一致的问题
    在这里插入图片描述

二. 多线程的先行发生原则happens-before

  1. 在jvm中,如果一个操作执行结果需要对另外一个操作可见或代码重排序,那么两个操作之间必须存在happens-before关系,也就是包含可见性有序性的约束
  2. 在java中可见性通过 volatile保证,可见性,有序性通过synchronized保证,
  3. **思考我们在实际开发中不是特殊需求很少用这两个功能的,为什么?,**因为java中根据JMM原则写有一个"Happens-Before先行发生原则"通过该原则,判断数据是否存在竞争,线程是否安全
  4. 那么happens-before的原则是什么? 共八条,比较重点的两条:
  1. 如果一个操作先行与另一个操作,那么第一个操作的执行结果对第二个操作是可见的,并且第一个操作的执行顺序在第二个操作执行之前
  2. 两个操作存在happens-before先后关系,并不意味着一定要按照happens-before先后顺序来执行,如果重排序之后的执行结果与按照happens-before先后关系执行结果一致,那么这种重排序是合法的
  1. happens-before 8 条(可理解为JMM逻辑规范)
  1. 次序规则: 一个线程内按照代码顺序,写在前面的先行发生与写在后面的操作,多线程下
  2. 锁定规则: 一个unlock操作先行发生与后面同一个锁的lock操作,简单说就是一个锁释放了unLock,下一个线程才能再去获取锁lock
  3. volatile变量规则: 对一个valatile变量,写操作先行发生于后面对这个变量的读操作,前面的写对后面的读是可见的,这里的"后面"是指时间层面的
  4. 传递规则: 如果操作A先行发生与操作B,而操作B有先行发生于操作C,则可以得出操作A先行发生与操作C
  5. 线程启动规则(Thread Start Rule): Thread对象的start启动,先行发生与该线程的每个动作执行
  6. 线程中断规则(Thread Interruption Rule): 对线程执行interrupt调用,先行发生于被中断线程的中断事件的发生,可以通过Thread.interrupted()检测是否发生中断
  7. 线程终止规则(Thread Termination Rule): 线程中的所有操作都先行发生与对此线程的终止检测,我们可以通过join()方法是否结束,通过isAlive()的返回值检测线程是否终止执行,理解为线程的终止一定在线程启动后面
  8. 对象终结规则( Finalizer Rule): 一个对象的初始化完成例如构造器执行结束,先行发生于他的finalize()方法开始
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值