偏向锁

当只有一个线程多次重复抢占锁同一资源时,即使是轻量级锁每次也至少需要两次(加锁、解锁)CAS操作。而此场景经Hotspot统计是比较容易出现的。所以为了减少不必要的资源浪费,偏向锁应运而生。

优点

只需要执行一次CAS即可获取锁

采用延迟释放锁策略

锁重入时,只需要判断mark_word.threadId(关于对象头的文章)是否为当前threadId即可

缺点

总体上只针对第一个线程有效,新线程获取锁时,会导致锁膨胀

锁膨胀时,会导致stop the world (STW)

与原生hashcode()互斥,导致偏向锁并非适应于所有的instance

如何获取一把偏向锁

前提

JVM偏向锁(-XX:+UseBiasedLocking)默认已开启

确认instance可用偏向锁可用,即mark word 锁状态标记位为 01

分支条件

匿名偏向

若instance处于匿名偏向状态(即初始状态,threadId为null),则执行CAS操作,将当前线程的id赋值到对象的mark word中,若成功则获取偏向锁成功,否则说明有多个线程竞争资源需要进行锁膨胀。

重偏向

即instance的Mark Word里的epoch与与klassOop.epoch标志位不一致时,表示此instance可被重偏向,此时新线程可以执行CAS操作进行锁抢占。

已偏向

即threadId已存在,且instance的epoch有效(与klassOop.epoch相等)此时instance处于已偏向状态。此时需比较当前threadId与mark_word.threadId的值,若相等,则可以继续占有锁,否则说存在资源竞争,需要进行锁膨胀。

锁膨胀过程

所有要竞争锁的线程到达安全区后,挂起对应线程。

遍历原锁持有线程的的调用栈的锁记录。将与被锁instance相关的锁记录改为轻量级锁相关的值。

更改被锁instance的Mark Word,将其指向最早的锁记录。

释放被挂起的相关线程。

偏向锁的骚操作

批量重偏向

Mark Word 里与偏向锁有关的信息除了threadId还有epoch,前面也提到epoch可以用来判断是否可以重偏向。那么他是如何实现的呢?

批量重偏向是针对两个线程串行共享instance资源场景(一个线程初始化instance传递给另一个线程)的优化。因为此时两个线程并不存在竞争,所以第二个线程可以继续使用偏向锁。

实现前提

Hotspot 通过在klassOop(可以理解为类的原型,其结构与instance一致)。里添加一个epoch字段,当一个Klass实例化instance一个时,便会以klassOop为原型初始化,epoch便被初始化在了instance的Mark Word中。

重偏向过程

当JVM执行到一个全局安全点的时候,挂起所有线程。

给KlassOop.epoch + 1.

给所有被偏向锁锁住的instance的Mark Word中的epoch + 1。或者采用启发式撤销偏向锁。

释放线程。

启发式撤销偏向

启发式撤销偏是针对重偏向的一种预防式优化。其逻辑很简单,通过设置一个阈值(k),一但epoch>k则执行撤销偏向锁操作,否者可以执行重偏向操作。

关于偏向锁的JVM参数

启用偏向锁

-XX:+UseBiasedLocking

偏向锁的延迟启动时间

偏向锁默认是在JVM启动4s后再初始化偏向锁,可用如下参数修改启动时间,设为0则表示立即启用。之所以这么设计是因为JVM启动的时候,如果立即启动偏向,有可能会因为线程竞争太激烈导致产生太多安全点挂起。

-XX:BiasedLockingStartupDelay=0

参考

java偏向锁_Java锁事之偏向锁相关推荐

  1. java 并发锁_Java并发教程–重入锁

    java 并发锁 Java的synced关键字是一个很棒的工具–它使我们可以通过一种简单可靠的方式来同步对关键部分的访问,而且也不难理解. 但是有时我们需要对同步进行更多控制. 我们要么需要分别控制访 ...

  2. java公平索非公平锁_java中的非公平锁不怕有的线程一直得不到执行吗

    首先来看公平锁和非公平锁,我们默认使用的锁是非公平锁,只有当我们显示设置为公平锁的情况下,才会使用公平锁,下面我们简单看一下公平锁的源码,如果等待队列中没有节点在等待,则占有锁,如果已经存在等待节点, ...

  3. java中什么是释放已经持有的锁_java多线程什么时候释放锁

    由于等待一个锁定线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不需要锁的时候及时释放锁是很重要的.在以下情况下,持有锁的线程会释放锁: 1.当前线程的同步方法.代码块执行结束的时候释放 ...

  4. java 同步锁_java线程中的同步锁和互斥锁有什么区别?

    在java中,同步锁和互斥锁英文关键字都是Synchronized,没有本质上的区别,两者都包括对资源的独占,使用起来没有区别.概念上的区别是 1:互斥是通过竞争对资源的独占使用,彼此没有什么关系,执 ...

  5. java 高并发_Java 高并发之无锁(CAS)

    Java 高并发之无锁(CAS) 本篇主要讲 Java中的无锁 CAS ,无锁 顾名思义就是 以不上锁的方式解决并发问题,而不使用synchronized 和 lock 等.. 1. Atomic 包 ...

  6. java 同步锁_Java多线程:synchronized同步锁的使用和实现原理

    作用和用法 在多线程对共享资源进行并发访问方面,JDK提供了synchronized关键字来进行线程同步,实现多线程并发访问的线程安全.synchronized的作用主要体现在三个方面:(1)确保线程 ...

  7. java线程 锁_Java多线程(二) 多线程的锁机制

    当两条线程同时访问一个类的时候,可能会带来一些问题.并发线程重入可能会带来内存泄漏.程序不可控等等.不管是线程间的通讯还是线程共享数据都需要使用Java的锁机制控制并发代码产生的问题.本篇总结主要著名 ...

  8. java 线程的可重入锁_java 多线程-可重入锁

    可重入锁:锁可以连续使用 计数器+判断进入的线程是不是已经锁定的线程,如果是那就不用等待,直接使用 public class my { public static void main(String[] ...

  9. 轻量级锁_Java高级架构师-Java锁的升级策略 偏向锁 轻量级锁 重量级锁

    欢迎关注头条号:Java小野猫 这三种锁是指锁的状态,并且是专门针对Synchronized关键字.JDK 1.6 为了减少"重量级锁"的性能消耗,引入了"偏向锁&quo ...

  10. java 偏向锁_Java并发之彻底搞懂偏向锁升级为轻量级锁

    网上有许多讲偏向锁,轻量级锁的文章,但对偏向锁如何升级讲的不够明白,有些文章还相互矛盾,经过对jvm源码(biasedLocking.cpp)的仔细分析和追踪,基本升级过程有了一个清晰的过程,现将升级 ...

最新文章

  1. Django值应用和分布式路由
  2. varchar 保存英文中文区别。
  3. 佛缘——宝华山隆昌寺之行
  4. 通过curl获取网页访问时间
  5. [leetcode] 24. Swap Nodes in Pairs
  6. C语言中忽略scanf的价值,c语言的scanf接收到底是忽略空格还是不忽略呢?
  7. java中进制转换_java中的进制转换
  8. MS SQL Server 事务回滚处理!
  9. Android 里的adb命令
  10. 科技创新全球资本财富盛会暨联盟系统2.0启动大会圆满举行
  11. 深度可分离卷积(Depthwise separable convolution)
  12. java xlsm_使用apache poi写入xlsm(Excel 2007)
  13. keyshot渲染玻璃打光_KeyShot渲染,打光这么打,效果倍儿棒!
  14. kotlin之开发经验整理
  15. 大学计算机课算绩点吗,大学体育成绩算入绩点吗?
  16. 三年磨一剑大话数据结构——数据结构起源、概念和术语
  17. JAVA 导入数据到Elasticsearch中
  18. 如何直观理解交叉熵及其优势?
  19. 网络1711班 C语言第一次作业批改总结
  20. ASC||码标准对照表

热门文章

  1. 520套电商行业响应式html5模板b2c商城购物网站模板HTML5化妆品电商网站模板IT类电子商务商城购物企业网站模板html5网页静态模板Bootstrap扁平化网站源码
  2. 还有3天就要上班了,面试中灵魂拷问的问题送给你
  3. a3图纸标题栏尺寸标准_标准CAD制图上A3图幅上的标题栏尺寸是多少
  4. CISSP怎么复习备考
  5. LabVIEW编程LabVIEW开发 控制雷赛运动控制器SMC604A例程与相关资料
  6. 一文看懂行业分类--基于wind行业分类标准
  7. VSTO程序基本知识(二)
  8. XRD测试常见问题及解答(二)
  9. 进销存excel_进销存管理系统excel模板
  10. IDEA中使用JUnit4(单元测试框架)超详细!