• ✨Synchronized底层实现---偏向锁


    偏向锁入口

    synchronized分为synchronized代码块和synchronized方法,其底层获取锁的逻辑都是一样的。

    要找到锁的入口,就要找到代码中对monitorenter指令解析的地方。在HotSpot中有两处对monitorenter进行了解析:一个是在bytecodeInterpreter.cpp#1816 ,另一个是在templateTable_x86_64.cpp#3667。

    bytecodeInterpreter

    bytecodeInterpreter是JVM中的字节码解释器,用C++实现了每一条jvm指令,如monitorenter,其优点是实现简单且比较容易理解,缺点是执行慢,后者是模板解析器templateInterpreter,他对每个指令都写了一段对应的汇编语言,启动时将每个指令和对应的汇编语言入口绑定,可以说将效率做到了极致,参考文章。在HotSpot中,只用到了模板解释器,所以,monitorenter的解析入口在

    HotSpot

    在HotSpot中,实现了两种具体的解释器,即模板解释器和C++解释器,它们分别由TemplateInterpreter子模块和CppInterpreter子模块实现。其中,模板解释器正是目前HotSpot的默认解释器.另外就是其实HotSpot从一开始就有模板解释器,而C++解释器反而是后来加进来的。前者源于HotSpot的前身Strongtalk,而后者源于Sun的另一个JVM——CVM,又名“CDC HotSpot Implementation”或者“CDC-HI”。CVM更早的前身是Sun的Classic VM。

    也就是说,这俩解释器没有任何血缘关系,前者并非将后者翻译为汇编。当时Sun之所以把后者加到HotSpot是在实现Itanium(IA-64)的移植时想偷懒,人肉写Itanium汇编挺烦的所以要实现Itanium版模板解释器不方便,他们就想到了把CVM的解释器移植过来,这样可以少写点汇编就能完成移植。结果一直以来HotSpot能运行的平台上只有Itanium版是真的用了这个C++解释器的,而其它平台上默认都在用模板解释器,但还是可以通过编译参数选择使用C++解释器。


    所以monitorenter的入口默认在模板解释器中,通过调用路径:templateTable_x86_64#monitorenter->interp_masm_x86_64#lock_object进入到偏向锁的入口中,macroAssembler_x86#biased_locking_enter,在这里可以看到生成的对应的汇编代码,在使用的时候,不是每次解析monitoreneter指令都会调用biased_locking_enter而是只在jvm启动的时候调用该方法生成对应的汇编指令,,之后对改代码的解析都是直接调用执行的汇编代码。


    其实bytecodeInterpreter的逻辑和templateInterpreter的逻辑是大同小异的,因为templateInterpreter中都是汇编代码,比较晦涩,所以看bytecodeInterpreter的实现会便于理解一点。但是有一点,在jdk1.8之前,bytecodeInterpreter中并没有偏向锁的逻辑。


    templateInterpreter汇编代码具体学习可以参考这篇文章

    偏向锁的获取流程

    偏向所锁,轻量级锁都是乐观锁,重量级锁是悲观锁。
    一个对象刚开始实例化的时候,没有任何线程来访问它的时候。它是可偏向的,意味着,它现在认为只可能有一个线程来访问它,所以当第一个
    线程来访问它的时候,它会偏向这个线程,此时,对象持有偏向锁。偏向第一个线程,这个线程在修改对象头成为偏向锁的时候使用CAS操作,并将
    对象头中的ThreadID改成自己的ID,之后再次访问这个对象时,只需要对比ID,不需要再使用CAS在进行操作。
    一旦有第二个线程访问这个对象,因为偏向锁不会主动释放,所以第二个线程可以看到对象时偏向状态,这时表明在这个对象上已经存在竞争了,检查原来持有该对象锁的线程是否依然存活,如果挂了,则可以将对象变为无锁状态,然后重新偏向新的线程,如果原来的线程依然存活,则马上执行那个线程的操作栈,检查该对象的使用情况,如果仍然需要持有偏向锁,则偏向锁升级为轻量级锁,(偏向锁就是这个时候升级为轻量级锁的)。如果不存在使用了,则可以将对象回复成无锁状态,然后重新偏向。
    轻量级锁认为竞争存在,但是竞争的程度很轻,一般两个线程对于同一个锁的操作都会错开,或者说稍微等待一下(自旋),另一个线程就会释放锁。 但是当自旋超过一定的次数,或者一个线程在持有锁,一个在自旋,又有第三个来访时,轻量级锁膨胀为重量级锁,重量级锁使除了拥有锁的线程以外的线程都阻塞,防止CPU空转。

  • 相关阅读:
    Andoird注册功能
    android注册功能
    寒假周总结六
    android登录功能
    Android登录功能
    android登录功能
    每日日报2021.1.24
    每日博客2021.1.23
    每日日报2021.1.22
    每日日报2021.1.21
  • 原文地址:https://www.cnblogs.com/charlottepl/p/13395989.html
Copyright © 2020-2023  润新知