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

    JVM内存模型(JAVA Memory Model,简称 JMM)

    JMM:用于定义变量(所有线程的共享变量,不能是局部变量)的访问规则。

    JMM将内存划分为两个区:主内存区和工作内存区

    • 主内存区:真实存放变量
    • 工作内存:主内存中变量的副本,供各个线程使用

    注意

    • 各个线程 只能访问自己私有的工作内存(不能访问其他线程的内存,也不能访问主内存)
    • 不同线程之间可以通过主内存间接的访问其他线程的工作内存。

    各个线程只能访问自己的工作内存,那么A线程如何获取B线程的值?

    1. 将线程B的数据同步到主内存(Save:将工作内存的数据刷到主内存)
    2. 线程A获取主内存中的最新数据(Load:主内存到工作内存)

    不同线程之间数据如何交互

    刚才介绍了 Save 和 Load 两个动作,但是不同线程之间数据交互的步骤不仅仅只有这两个,下面我们完整介绍一下交互步骤。

    1. Lock : 将主内存中的数据,标识为一条线程的独占状态。
    2. Read : 将主内存中的变量,读取到工作内存中。
    3. Load:将上一步读取的变量,拷贝到变量副本当中。
    4. Use:将工作内存中的变量副本,传递给线程去使用。
    5. Assign:将线程正在使用的变量,传递给工作内存中的变量副本。
    6. Store:将工作内存中变量副本的值,传递到主内存中。
    7. Write:将变量副本作为主内存中的变量进行储存。
    8. UnLock:解除线程的独占状态。

    JVM要求以上的八个动作必须是原子性的。

    但是JVM对于64位的数据类型(long/double)有非原子性协议!!long和double占用的字节数都是8,也就是64bits。在32位操作系统上对64位的数据的读写要分两步完成,每一步取32位数据。这样对double和long的赋值操作就会有问题:如果有两个线程同时写一个变量内存,一个进程写低32位,而另一个写高32位,这样将导致获取的64位数据是失效的数据。因此需要使用volatile关键字来防止此类现象。volatile本身不保证获取和设置操作的原子性,仅仅保持修改的可见性。但是java的内存模型保证声明为volatile的long和double变量的get和set操作是原子的。

  • 相关阅读:
    redis---01
    mysql优化-----索引覆盖
    mysql优化-------Myisam与innodb引擎,索引文件的区别
    mysql优化-----多列索引的左前缀规则
    mysql---列的选取原则
    boogo08---中间件
    goroutine pool,WaitGroup,chan 示例
    Android开发 |常见的内存泄漏问题及解决办法
    Android中FragmentPagerAdapter对Fragment的缓存(二)
    Android中FragmentPagerAdapter对Fragment的缓存(一)
  • 原文地址:https://www.cnblogs.com/leizzige/p/14165305.html
Copyright © 2011-2022 走看看