zoukankan      html  css  js  c++  java
  • 48 多线程中 synchronized 锁升级的原理是什么?

    多线程中 synchronized 锁升级的原理是什么?

    答:

    什么是锁升级(锁膨胀)?

      JVM优化synchronized的运行机制,当JVM检测到不同的竞争状态时,就会根据需要自动切换到合适的锁,这种切换就是锁的升级。升级是不可逆的,也就是说只能从低到高,也就是偏向-->轻量级-->重量级,不能够降级

      锁级别:无锁->偏向锁->轻量级锁->重量级锁
     

    无锁:没有对资源进行锁定,所有的线程都能访问并修改同一个资源,但同时只有一个线程能修改成功,其他修改失败的线程会不断重试直到修改成功。
     

    偏向锁:对象的代码一直被同一线程执行,不存在多个线程竞争,该线程在后续的执行中自动获取锁,降低获取锁带来的性能开销。偏向锁,指的就是偏向第一个加锁线程,该线程是不会主动释放偏向锁的,只有当其他线程尝试竞争偏向锁才会被释放。

    偏向锁的撤销,需要在某个时间点上没有字节码正在执行时,先暂停拥有偏向锁的线程,然后判断锁对象是否处于被锁定状态。如果线程不处于活动状态,则将对象头设置成无锁状态,并撤销偏向锁;

    如果线程处于活动状态,升级为轻量级锁的状态。
     

    轻量级锁:轻量级锁是指当锁是偏向锁的时候,被第二个线程 B 所访问,此时偏向锁就会升级为轻量级锁,线程 B 会通过自旋的形式尝试获取锁,线程不会阻塞,从而提高性能。

    当前只有一个等待线程,则该线程将通过自旋进行等待。但是当自旋超过一定的次数时,轻量级锁便会升级为重量级锁;当一个线程已持有锁,另一个线程在自旋,而此时又有第三个线程来访时,轻量级锁也会升级为重量级锁。
     

    重量级锁:指当有一个线程获取锁之后,其余所有等待获取该锁的线程都会处于阻塞状态。

    重量级锁通过对象内部的监视器(monitor)实现,而其中 monitor 的本质是依赖于底层操作系统的 Mutex Lock 实现,操作系统实现线程之间的切换需要从用户态切换到内核态,切换成本非常高。
     

    锁状态对比:

    偏向锁 轻量级锁 重量级锁
    适用场景 只有一个线程进入同步块 虽然很多线程,但是没有冲突:多条线程进入同步块,但是线程进入时间错开因而并未争抢锁 发生了锁争抢的情况:多条线程进入同步块并争用锁
    本质 取消同步操作 CAS操作代替互斥同步 互斥同步
    优点 不阻塞,执行效率高(只有第一次获取偏向锁时需要CAS操作,后面只是比对ThreadId) 不会阻塞 不会空耗CPU
    缺点 适用场景太局限。若竞争产生,会有额外的偏向锁撤销的消耗 长时间获取不到锁空耗CPU 阻塞,上下文切换,重量级操作,消耗操作系统资源

    原文链接: https://www.cnblogs.com/ConstXiong/p/11687975.html

    另一篇博文: https://www.cnblogs.com/jxxblogs/p/11890563.html

  • 相关阅读:
    Checking Types Against the Real World in TypeScript
    nexus pip proxy config
    go.rice 强大灵活的golang 静态资源嵌入包
    几个golang 静态资源嵌入包
    rpm 子包创建学习
    Rpm Creating Subpackages
    ava 类似jest snapshot 功能试用
    ava js 测试框架基本试用
    The Architectural Principles Behind Vrbo’s GraphQL Implementation
    graphql-compose graphql schema 生成工具集
  • 原文地址:https://www.cnblogs.com/ynzj123/p/12847190.html
Copyright © 2011-2022 走看看