zoukankan      html  css  js  c++  java
  • java面试-Java内存模型(JMM)

    一、并发编程两个关键问题

    线程之间如何通信、同步。java并发采用的是共享内存模型

    二、JMM内存模型的抽象结构
    描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式。

    JMM决定一个线程对共享变量的写入何时对另一个线程可见。

    JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(Main Memory)中,每个线程都有一个私有的本地内存(Local Memory),本地内存中存储了该线程读/写共享变量的副本。

     

    如果线程A与线程B之间要通信的话,必须要经历下面2个步骤。

    1)线程A把本地内存A中更新过的共享变量刷新到主内存中去。

    2)线程B到主内存中去读取线程A之前已更新过的共享变量。

     

    三、JMM内存模型三大特性

    1、原子性

    • AtomicInteger
    • 使用 synchronized 互斥锁来保证操作的原子性

    2、可见性:

    • volatile,会强制将该变量自己和当时其他变量的状态都刷出缓存。
    • synchronized,对一个变量执行 unlock 操作之前,必须把变量值同步回主内存。
    • final,被 final 关键字修饰的字段在构造器中一旦初始化完成,并且没有发生 this 逃逸(其它线程通过 this 引用访问到初始化了一半的对象),那么其它线程就能看见 final 字段的值。

    3、有序性

    源代码 -> 编译器优化的重排 -> 指令并行的重排 -> 内存系统的重排 ->最终执行的命令

    重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性

    处理器在进行重排时必须考虑数据的依赖性,多线程环境线程交替执行,由于编译器优化重排的存在,两个线程中使用的变量能否保证一致性是无法确定的。

    1)编译器优化的重排:

         编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。

     

          

    2)指令并行的重排  

          如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。

     

    3)内存系统的重排

         由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。

    • volatile 关键字通过添加内存屏障(Memory Barriers)的方式来禁止特定类型的处理器重排序,即重排序时不能把后面的指令放到内存屏障之前。
    • synchronized 保证每个时刻只有一个线程执行同步代码,相当于是让线程顺序执行同步代码。

  • 相关阅读:
    浏览器HTML5支持程度测试
    Unit testing Cmockery 简单使用
    Linux likely unlikely
    Android development tools line_endings hacking
    Linux C enum
    Android 系统内置App JNI
    Android Broadcast Receiver
    Android获取SharedPreferences失败,且App无法启动
    Sublime-text markdown with Vim mode and auto preview
    遍历Map key-value的两种方法
  • 原文地址:https://www.cnblogs.com/wjh123/p/11094622.html
Copyright © 2011-2022 走看看