• JVM Java内存模型


    硬件的效率与一致性                                                    

    在计算机中,内存的读写与处理器的计算速度有几个级的差距.这样会严重影响到TPS(Transations Per Second).
    所以会为每个处理器配一个高速缓存以缓和处理器的速度.而在计算机中,多个处理器共享一个内存,这个时候数据的读写操作将不会安全
     

    什么是内存模型                                                                       

    名词解释:JMM(Java Memory Model),即Java内存模型
    如果想要深入了解Java并发编程,必须先学习好JMM,JMM定义了jvm虚拟机在计算机内存中的工作方式

    工作内存与主内存                                                                  

    java内存模型规定了所有变量都必须存储在主内存中.
    线程对变量的所有操作(赋值与读取)都必须在工作内存中进行,而不能直接读写主内存的变量
    线程间也无法直接访问对象工作内存中的变量,而是通过主内存来进行交互(线程间变量值的传递需要主主内存来完成)

    内存间相互交互                                                    

    工作内存与主内存之间有规定的协议.即一个变量如何从主内存拷贝到工作内存中,又如何从工作内存同步变量到主内存中.以下有8个操作指令:
      1.lock(锁定)作用于主内存的变量中,锁定并让某线程独享
      2.unlock(解锁)作用于主内存的变量中,解锁变量以让其他线程访问
      3.read(读取)作用于主内存变量中,以便工作内存下一步的load操作
      4.load(载入)作用于工作内存中,载入从主内存中读取的变量
      5.use(使用)作用于工作内存中.他把工作内存中的值传递给执行引擎,每当虚拟机需要使用到变量值的时执行这个操作
      6.assign(赋值)作用于工作内存中,他把从执行引擎中返回的最新值赋值给变量,每当虚拟机遇到一个给变量赋值的字节指令码时执行这个操作
      7.store(存储)作用于工作内存中,它把工作内存中的值传递到主内存中,以便下一步的write操作
      8..write(写入)作用于主内存中,它把从store操作获取的值更新到内存中
    上述的8中基本操作必须满足以下规则:
      1.不允许read、load和store、write单独出现
      2.不允许线程对其最近的assign操作,即工作内存中的变量改变后必须同步到主内存中
      3.不允许一个线程无原因的同步变量到主内存中
      4.一个新的变量只能从主内存中产生.工作内存中不允许使用未被初始化(load、assign)的变量
      5.变量最多只能同时被一个线程执行load操作,且可以操作任意次,相对的需要执行一样多次的unlock操作.
      6.lock操作时会清除工作内存中的变量的值.当需要读取时再从主内存中载入
      7.如果一个变量没有进行lock操作那就不允许执行unlock操作,也不能去unlock其他线程锁定的变量
      8.在执行unlock操作前变量必须先同步到主内存中

    Volatile变量的特殊性                                                                                 

    关键字volatile可以说是Java虚拟机最轻量级的同步机制
    一个变量被定义为volatile,它将具备两种特性:
      1.保证变量对所有线程的“可见性”变量的改变将会同步更新到其他的拥用该变量的线程中,而普通的变量不能做到这里点,普通变量的值在线程间传递均需要通过主内存来完成,需要注意的是:volatile只能保证变量的可见性,在多线程的环境中也并非是绝对安全的
      2.使用volatile变量表示禁止指令重排序优化
      线程安全指标:可见性、原子性、有序性
    Java内存模型是围绕着可见性、原子性、有序性这三个特征建立
      1.原子性(Atomicity):
        由Java内存模型来保证原子性的操作有read、load、assign、use、store、write, 大致可以认为基本数据类型的访问读写是具备原子性。如果需要一个更大的原子性保证,还有lock和unlock,在虚拟机中没有直接把这两操作给用户使用,而是隐式的在字节                           码添加指令monitorenter和monitorenter进行操作.这两个字节码对象jdk代码中就是同步块-synchronize关键字
      2.可见性(Visibility):
        可见性是指当线程改变了共享的变量,其他线程能够马上知道此次的修改
        2.1:volatile就验证了这一点
        2.2:synchronize也是可见性的,因为在其unlock操作之前,必须把变量值同步到主内存中
        2.3 final也是有可见行.因为被final修饰的字段一旦被构造器初始化完成,并且构造器没把this传递出去,那在其他线程中就能看见final字段的值(WTF?不懂)
      3.有序性(Ordering):
        编译器或者运行时环境为了优化程序性能,会对代码进行重排序.而volatile关键字本身就禁止指令重排序,synchronize则是由“一个变量在同一时刻只能有一个线程进行lock操作”获得.持有同一个锁的两个同步块只能串行的进行(why?)

    先行发生happends-before原则                                                               

    如果java内存模型中只能靠volatile和synchronize关键字来有序性的执行,那么有一些操作起来就会非常频繁,所以Java语言中有一种现行发生happens-before的原则,如下
    程序次序规则:在一个线程内,按照控制流顺序,控制流前面的操作先行发生于控制流后面的操作,说“控制流”是因为还要考虑到分支、循环结构
    管程锁定规则:unlock操作必须先行发生于同一个锁的lock操作
    volatile规则:变量的写操作必须先于读操作
    线程启动规则:thread的start()方法先于任何方法
    线程终止规则:线程中的所有方法都先行与对此线程终止检测
    线程中断规则:对线程的interrupt()方法调用先行发生于被中断线程的代码检测到中断事件的发生
    对象终结规则:对象的初始化完成必须先发生于finalize()方法的开始
    传递新:A操作先于B操作,B操作先于C操作,则A操作一定先于C操作
     
  • 相关阅读:
    RIP 动态路由
    9.28 二叉树计数
    9.31 取数理论
    花园
    迟滞变化
    AutoHotkey之自问自答
    几种常见的滤波处理
    快速排序(Quicksort)
    浅谈VBA
    新的开始
  • 原文地址:https://www.cnblogs.com/zewen/p/7078592.html
Copyright © 2020-2023  润新知