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

    基本概念

    1.并发编程模型

    线程之间的通信机制有两种:共享内存和消息传递。Java的并发采用的是隐式的共享内存模型。
    Java内存模型(JMM)是围绕着在并发过程中如何处理原子性、可见性和有序性来建立的。

    • 原子性:基本数据类型的访问读写是具备原子性的(针对long和double有非原子性协定),synchronized块之间的操作也具备原子性。
    • 可见性:当一个线程修改了共享变量(主内存中)的值,其他线程能够立即得知这个修改。
    • 有序性:线程内表现为串行的语义,从一个线程观察另一个线程,由于指令重排序和工作内存与主内存同步延迟,看到的操作是无序的。

    2.内存模型抽象

    • 主内存:存储线程之间共享变量,所有存储在堆内存中的实例域、静态域和数组元素在线程之间共享。
    • 工作内存:线程私有,存储该线程读写共享变量的副本,它是JMM的抽象概念,并不存在,它涵盖了缓存、写缓冲区、寄存器及其他硬件和编译器的优化。
    • JMM抽象示意图:

    3.重排序

    在执行程序时,编译器和处理器会对指令重排序,重排序分三种类型:

    • 编译器优化的重排序
    • 指令级并行的重拍序
    • 内存系统的重排序
      编译器和处理器遵循as-if-serial语义(不管怎么重排序,都不能改变单线程程序的执行结果),不会对存在数据依赖关系的操作重排序。

    4.内存屏障指令

    JMM把内存屏障指令分为四类:

    • LoadLoad
    • LoadStore
    • StoreLoad
    • StoreStore

    5.happens-before规则

    在JMM中,如果一个操作执行的结果需要对另一个操作可见,这两个操作之间必须存在happens-before关系。
    happens-before规则仅仅要求前一个操作的结果对后一个操作可见,且前一个操作按顺序排在第二个操作之前。

    同步机制

    1.volatile

    对一个volatile共享变量的单个读写操作,相当于对普通共享变量的读写操作使用同一个锁来同步。
    volatile保证了多线程操作变量的可见性(新值能立即同步到主内存,每次使用前立即从主内存刷新)和有序性(volatile本身就包含了禁止指令重排序的语义),但不能保证原子性(对任意单个volatile变量的读写具有原子性,但对于volatile++这种复合操作不具有原子性)。

    2.锁

    锁除了让临界区互斥执行外,还可以让释放锁的线程向获取同一个锁的线程发送消息。
    ReentrantLock的实现依赖于Java同步框架AQS,AQS使用一个整型的volatile变量state来维护同步状态。
    锁释放和获取的内存语义的实现使用了volatile变量的读写所具有的内存语义和CAS自带的volatile读写的语义。

    • 公平锁:锁获取时先读volatile变量,锁释放时最后写volatile变量。
    • 非公平锁:锁获取时先使用CAS更新volatile变量,锁释放时最后写volatile变量。

    3.final

    final保证了可见性(被final修饰的字段在构造器中一旦初始化完成,并且构造器没有把this的引用传递出去,那在其他线程中就能看见final的值)。

    参考书籍

    《深入理解Java内存模型》、《深入理解Java虚拟机 第二版》

  • 相关阅读:
    SpringMVC传值、转发、重定向例子
    内存、指针操作函数
    文件、磁盘操作函数
    字符串、数组操作函数 Copy Concat Delete Insert High MidStr Pos SetLength StrPCopy TrimLeft
    Delphi代码模拟“显示桌面”的功能
    SQLite 入门教程(四)增删改查,有讲究
    NET Core
    Publisher/Subscriber 订阅-发布模式
    数据分片
    C#调用Java方法
  • 原文地址:https://www.cnblogs.com/pycrab/p/9732225.html
Copyright © 2011-2022 走看看