zoukankan      html  css  js  c++  java
  • 并发学习-1

    一、基本概念

    • 程序:代码,为了完成某一任务的,代码序列 静态
    • 进程:程序完成某一任务的一次运行 动态
    • 线程:一个进程由多个线程组成

    二、JVM与线程

      JVM什么时候启动? 答:类被调用  JVM线程包含其他线程(main)

    三、JVM的内存区域

      方法区,堆、程序计数器、本地方法栈,java栈 等区域。详情请看图1-1

    • 方法区:类信息、常量、static、JIT(及时编译器)(共享区域)
      1. 类信息:由classLoader(类加载器)
      2. 常量:成员变量
      3. static变量:静态变量
      4. JIT:即时编译
    • 堆:实例对象、GC(共享区域)OOM指的是存在内存溢出的风险
    • java栈:运行时的内存模型 图1-2   OOM指的是存在内存溢出的风险
    • 程序计数器(PC):java线程的私有数据,这个数据就是记录执行下一指令的地址
    • 本地方法栈:与虚拟机的native有关系

    四、java的内存模型 JMM(规范,抽象模型) 图1-3

    • 主内存:共享数据,引用类型的对象放在主内存
    • 工作内存:私有数据,线程就是在工作内存中存在的,基本数据类型直接存在工作内存,引用的类型的的地址放在工作内存。
    • 工作方法:
      1. A线程如果要修改私有数据,会在A线程工作空间找,没找到将会去主内存中找到并复制到工作空间,并进行修改。
      2. B线程如果要修改共享数据,同理上面,但是区别于复制到工作空间后修改完毕会再刷新(赋给)主内存。为什么要这样设计?为了确保信息的保密性,个人理解相当于你和别人借钱要买某保险,你一定是先将钱借到手,再去买,而不是带着业务员去借钱对象的家里面买保险

    五、硬件内存架构与java内存模型

    • 硬件内存架构  图1-4 CPU只的是CPU运行区(处理器内存,并不是4核 2核CPU概念,指的是CPU分配时间片)
      1. CPU缓存一致性:内存中存在变量A=1,CPU1获取A的值之后要进行修改A=2,此时CPU2获取变量A有可能是1也可能是2.因为CPU修改完毕后会通过cache(缓存)刷新到内存中。如果还没有保存到内存中那么CPU2将获取的A=1,反之A=2.。此时会出现并发不同步(不安全)
      2. 解决的问题
        • 总线加锁:此种方法很影响CPU的吞吐量,虽然能保证数据的一致性,但是牺牲了大量的时间,类似于java中的方法使用sysnchronize,同一时间只能一个CPU用。
        • cache缓存一致性协议(Intel协议,MESI协议):CPU从cache获取变量到寄存器中修改完毕后,会将cache中的变量设置一个状态 cache Line为无效类似于state=0,其他CPU如果检测到cache Line为0时则直接从内存中获取变量的value,防止其他CPU从cache读取脏数据
    • 线程与硬件处理器 图1-5    进程>线程>操作系统OS>CPU
    • java内存模型与硬件内存架构的关系  图1-6
      1. 图中可以看到是JMM(虚拟机数据模型)与CUP内存架构是交叉关系,所以会造成数据不一致性
    • java内存模型的必要性
    • java内存模型的作用:规范内存数据(主内存)与工作空间(工作内存)的交互

    六、并发编程的三个重要特征

    • 原子性:不可分割的,同生共死。
    • 可见性:一个线程只能读写自己的工作空间(工作内存)的cache
    • 有序性:程序中的顺序不一定就是执行顺序,
      1. 编译的时候会重排,
      2. 指令也会重排,
      3. 为了提高效率
      4. 例子:int a=1;int b=2;int c=0; c=a+b; int d=0; 因为变量c比较复杂,所以效率慢,排序后先执行d=0;再去执行c=a+b;
        • 单线程重排规则(编译优化):as-if-seria规则,重排后不影响执行结果
        • 多线程重排规则(指令优化):happens-before规则,程序次序原则(程序的结果不能变化),锁定原则(后一次加锁必须等前一次解锁),Volatile原则(霸道原则),传递原则(A语句再B语句前执行,最后C执行,得出的结论是A必须在C语句前执行。A--B--C    A--C)。

    七、JMM(java内存模型)三大特性的保证

    • JVM的原子性
      1. int x = 10; 基础类型是存在工作空间,所以写入的时候就是存在原子性。如果是私有数据具有原子性,如果是共享数据则没有原子性。先读后写则不存在原子性
      2. int y = x;没有原子性。原因:把数据x读取到工作空间(原子性) 把x的值写到y(原子性)但是读写后则不存在原子性
      3. int i++;没有原子性。原因:读i到工作空间,然后写入i+1,内存刷新结果,单个执行都具有原子性,但是放到一起不具备原子性。
      4. int Z=z+1;没有原子性,原因:先将z读到工作空间,然后计算z+1,赋值给Z,内存刷新结果。
      • 结论:多个原子性的操作合并到一起就没有原子性。怎么保证原子性呢?
      • 保证方式:
      1. Synchronized
      2. JUC Lock的lock加锁
    • JMM的可见性
      1. 工作空间修改了变量后,刷新给内存后,怎么保证其他工作空间队内存的变量的可见性
      • 保证可见性方式:
        1. 使用Volatile:再JMM模型上实现MESI协议。
        2. Sysnchronized:加锁
        3. JUC LOCK的lock加锁
    • JMM的有序性
      • 保证方式:
      1. Volatile
      2. Synchronized

           Happens-before规则

    八、总结

    • JVM内存区域和JMM(抽象java内存模型)的关系
    • JMM和硬件的关系
    • JMM和并发编程三个重要特征  *(有序性 as-if-seria和happens-before)

    欢迎大家来提问,如果有不理解的可以再评论区提出,我会定时解惑。

    同舟共济,新海同航

    图1-1                                                                                    图1-2                      图1-3

     

              图1-4                图1-5                图1-6

                                        

    java中的start如何调用run方法?

    1、模板模式、线程是对应操作系统的线程,一一对应的。因为需要将你想做的逻辑让操作系统去执行。

    start---start0---native---pthread_create(java_start){

    }

    void{

    java_start jni反射调用java run

    }

  • 相关阅读:
    C#创建自定义配置节
    linux下安装nginx
    linux查看防火墙状态和对外开放的端口状态
    js 获取二级域名
    .net core 获取本地ip及request请求端口
    《趣谈 Linux 操作系统》学习笔记(二):对 Linux 操作系统的理解
    《趣谈 Linux 操作系统》学习笔记(一):为什么要学 Linux 及学习路径
    Redis Cluster集群
    Redis的主从复制与Redis Sentinel哨兵机制
    Redis持久化方案
  • 原文地址:https://www.cnblogs.com/gnwzj/p/10541855.html
Copyright © 2011-2022 走看看