zoukankan      html  css  js  c++  java
  • java内存模型JMM

    基本概念

    程序:代码,完成某一件任务,代码序列(静态的概念)
    进程:程序在某些数据上的一次运行(动态的概念)
    线程:一个进程可能包含一个或多个线程(占有资源的独立单元)

    JVM与线程

    JVM是在类被调用的时候才会被启动。先有JVM线程,然后才其他(main)线程(JVM创建了其他线程,)。

    JVM 内存区域


    信息共享

    方法区:类信息(由类加载器加载)、常量、static、JIT (动态编译的代码)。(反射操作的地方)。
    Java堆区:实例对象 GC工作主要区域 (OOM)。
    数据不共享
    VM stack(虚拟机栈):Java方法在运行的内存模型 (OOM)
    如果虚拟机栈内存溢出指的是整体内存不足,不是单个栈帧内存不足,栈帧的内存是有大有小的。

    PC(程序计数器):java线程的私有数据,这个数据就是执行下一条指令的地址
    Native method stack: JVM的本地方法

    java内存模型 Java memory model(JMM,抽象的概念)

    主内存:共享的信息
    工作内存:私有信息,基本数据类型,直接分配到工作内存,引用的地址存放在工作内存,引用的对象存放在堆中
    工作方式:
    A 线程修改私有数据,直接在工作空间修改
    B 线程修改共享数据,把数据复制到工作空间中去,在工作空间中修改,修改完成以后,刷新内存中的数据

    JMM三个特征

    原子性:不可分割 (类似与银行转账,必须要一个加钱一个减钱)
    A) X=10 单纯的写是有原子性。如果是私有数据具有原子性,如果是共享数据没原子性(读写)

    B) Y=x 没有原子性

    a) 把数据X读到工作空间(原子性)

    b) 把X的值写到Y(原子性)

    C) I++ 没有原子性

    a) 读i到工作空间

    b) +1;

    c) 刷新结果到内存

    D) Z=z+1 没有原子性

    a) 读z到工作空间

    b) +1;

    c) 刷新结果到内存

    多个原子性的操作合并到一起没有原子性

    保证方式:

    Synchronized

    JUC Lock的lock

    可见性:线程只能操作自己工作空间中的数据

    加锁:Synchronized、Lock

    关键字:Volatile:在JMM模型上实现MESI协议

    有序性:程序中的顺序不一定就是执行的顺序。

    (编译重排序(编译优化)、指令重排序(指令优化),为了优化代码提高效率)

    as-if-aeria原则:

    单线程中重排后不影响执行的结果。

    Happens-before原则:

    1. 程序次序规则:在-一个线程内,按照程序代码顺序,书写在前面的操作先行发生于书写在后面的操作。准确地说,应该是控制流顺序而不是程序代码顺序,因为要考虑分支。循环等结构。

    2. 管程锁定规则:一个unlock操作先行发生于后面对同一个锁的lock操作。 这里必须强调的是同一个锁,而“后面"是指时间上的先后顺序。

    3. volatile变量规则:对一个volatile变 量的写操作先行发生于后面对这个变量的读操作,这里的"后面"同样是指时间上的先后顺序。

    4. 线程启动规则: Thread对象的start()方法先行发生于此线程的每-一个动作。

    5. 线程终止规则:线程中的所有操作都先行发生于对此线程的终止检测,我们可以通过Thread,join () 方法结束、Thread.isAlive ()的返回值等手段检测到线程已经终止执行。

    6. 线程中断规则:对线程interrupt()方 法的调用先行发生于被中断线程的代码检测到中断事件的发生,可以通过Thread.interrupted()方法检测到是否有中断发生。

    7. 对象终结规则: -个对象的初始化完成(构造函数执行结束)先行发生于它的finalize()方法的开始。

    Happens-Before的1个特性:传递性。A--B--C A--C A在B前,B在C前。可以得到A的语句必须要在C语句前面执行。

    Java内存模型涉及的几个关键词:锁、volatile字段、 final修 饰符与对象的安全发布。

    1. 锁操作是具备happens- before关系的,解锁操作happens-before之后对同一把锁的加锁操作。实际上,在解锁的时候,JVM需要强制刷新缓存,使得当前线程所修改的内存对其他线程可见。

    2. volatile字段可以看 成是一-种不保证原子性的同步但保证可见性的特性,其性能往往是优于锁操作的。但是,频繁地访问volatile字段也会出现因为不断地强制刷新缓存而影响程序的性能的问题。

    3. final修饰的实例字段则是涉及到新建对象的发布问题。当一个对象包含final修饰的实例字段时,其他线程能够看到已经初始化的final实例字段,这是安全的。

    Java内存模型底层怎么实现的

    主要是通过内存屏障(memory barrier)禁止重排序的,即时编译器根据具体的底层体系架构,将这些内存屏障替换成具体的CPU指令。对于编译器而言,内存屏障将限制它所能做的重排序优化。而对于处理器而言,内存屏障将会导致缓存的刷新操作。比如,对于volatile,编译器将在volatile字段的读写操作前后各插入一些内存屏障。

  • 相关阅读:
    DWR2.0的DefaultContainer can't find a classes异常的解决方案
    IIS7.5(FastCGI)PHP7安装手记
    android手机一句话备忘录
    设计模式学习每日一记(21.叠代器模式)
    设计模式学习每日一记(20.中介者模式)
    C&C++多系统集成需要注意的问题
    设计模式学习每日一记(23.责任链模式)
    设计模式学习每日一记(22.访问者模式)
    源码阅读工具总结
    zte v880刷机入门篇
  • 原文地址:https://www.cnblogs.com/yangk1996/p/12656423.html
Copyright © 2011-2022 走看看