偏向锁

偏向第一个拿到锁的线程。

即第一个拿到锁的线程,锁会在对象头 Mark Word 中通过 CAS 记录该线程 ID,该线程以后每次拿锁时都不需要进行 CAS(指轻量级锁)。

如果该线程正在执行同步代码块时有其他线程在竞争(指其他线程尝试 CAS 让 Mark Word 设置自己的线程 ID),会被升级为轻量级锁。

如果其他线程发现 Mark Word 里记的不是自己,且发现原持有偏向锁的线程已经执行完同步代码块,会尝试 CAS 把 Mark Word 中的改为自己的线程 ID。

轻量级锁

轻量级锁就是通过 CAS 进行加锁的。

JVM 会给线程的栈帧中创建一个叫锁记录 Lock Record 的空间,把对象头 Mark Word 复制到该空间里(Displaced Mark Word),并通过 CAS 尝试把原对象头 Mark Word 中锁记录指针指向该锁记录。如果成功,表示线程拿到了锁。如果失败,则进行自旋(自旋锁),自旋超过一定次数时升级为重量级锁,这时该线程会被内核挂起。

自旋锁

轻量级锁膨胀为重量级锁前,线程在执行 monitorenter 指令进入等待队列时,会通过自旋去尝试获得锁。

如果自旋超过一定次数时还未拿到锁,就会进入阻塞状态,等待内核来调度。此时会发生内核态与用户态之间的上下文切换,所以会影响性能(引入自旋锁就是为了减少这个开销)。

因为后面的线程也先进行自旋尝试获取锁,所以这对于已被阻塞的那些线程来说,会不公平

重量级锁

重量级锁就是通过内核来操作线程。因为频繁出现内核态与用户态的切换,会严重影响性能。

升级为重量级锁时会在堆中创建 monitor 对象,并将 Mark Word 指向该 monitor 对象。monitor 中有 cxq(ContentionList),EntryList ,WaitSet,owner:

图片来自:死磕Synchronized底层实现--重量级锁

锁升级的流程图

图片来自:Java Synchronised机制

锁降级

Hotspot 在 1.8 开始有了锁降级。在 STW 期间 JVM 进入安全点时如果发现有闲置的 monitor(重量级锁对象),会进行锁降级。

Java锁优化--JVM锁降级

为什么锁信息存放在对象头里?

死磕Synchronized底层实现--概论 中:

因为在Java中任意对象都可以用作锁,因此必定要有一个映射关系,存储该对象以及其对应的锁信息(比如当前哪个线程持有锁,哪些线程在等待)。一种很直观的方法是,用一个全局map,来存储这个映射关系,但这样会有一些问题:需要对map做线程安全保障,不同的synchronized之间会相互影响,性能差;另外当同步对象较多时,该map可能会占用比较多的内存。

所以最好的办法是将这个映射关系存储在对象头中,因为对象头本身也有一些hashcode、GC相关的数据,所以如果能将锁信息与这些信息共存在对象头中就好了。

也就是说,如果用一个全局 map 来存对象的锁信息,还需要对该 map 做线程安全处理,不同的锁之间会有影响。所以直接存到对象头。

其他文章

【死磕Java并发】—–深入分析synchronized的实现原理

【死磕 Java 并发】—– synchronized 的锁膨胀过程

【转载】Java中的锁机制 synchronized & 偏向锁 & 轻量级锁 & 重量级锁 & 各自优缺点及场景 & AtomicReference

死磕Synchronized底层实现--概论

synchronized的锁升级/锁膨胀的更多相关文章

  1. Synchronized锁升级

    Synchronized锁升级 锁的4中状态:无锁状态.偏向锁状态.轻量级锁状态.重量级锁状态(级别从低到高) 为什么要引入偏向锁? 因为经过HotSpot的作者大量的研究发现,大多数时候是不存在锁竞 ...

  2. Synchronized关键字和锁升级,详细分析偏向锁和轻量级锁的升级

    原文链接:https://blog.csdn.net/tongdanping/article/details/79647337 1.锁升级锁的4中状态:无锁状态.偏向锁状态.轻量级锁状态.重量级锁状态 ...

  3. 锁升级(Lock Escalations)——它们经常发生么?

    前段时间,我写了一些SQL Server里锁升级的基础知识,还有它是如何影响执行计划的.今天,我想进一步谈下锁升级: 锁升级什么时候发生? 通常在SQL Server里如果在SQL语句里你请求的行数超 ...

  4. 如何解决 SQL Server 中的锁升级所致的阻塞问题

    概要 锁升级为表锁插入转换很多细粒度的锁 (如行或页锁) 的过程.Microsoft SQL Server 动态确定何时执行锁升级.作出决定之前,SQL Server 将特定的扫描,整个事务,并且用于 ...

  5. synchronized(三) 锁的膨胀过程(锁的升级过程)深入剖析

    警告⚠️:本文耗时很长,先做好心理准备................哈哈哈 本篇我们讲通过大量实例代码及hotspot源码分析偏向锁(批量重偏向.批量撤销).轻量级锁.重量级锁及锁的膨胀过程(也就是 ...

  6. java架构之路(多线程)synchronized详解以及锁的膨胀升级过程

    上几次博客,我们把volatile基本都说完了,剩下的还有我们的synchronized,还有我们的AQS,这次博客我来说一下synchronized的使用和原理. synchronized是jvm内 ...

  7. Synchronized锁性能优化偏向锁轻量级锁升级 多线程中篇(五)

    不止一次的提到过,synchronized是Java内置的机制,是JVM层面的,而Lock则是接口,是JDK层面的 尽管最初synchronized的性能效率比较差,但是随着版本的升级,synchro ...

  8. 并发编程:synchronized 锁升级过程的验证

        关于synchronized关键字以及偏向锁.轻量级锁.重量级锁的介绍广大网友已经给出了太多文章和例子,这里就不再重复了,也可点击链接来回顾一下.在这里来实战操作一把,验证JVM是怎么一步一步 ...

  9. 深入并发锁,解析Synchronized锁升级

    这篇文章分为六个部分,不同特性的锁分类,并发锁的不同设计,Synchronized中的锁升级,ReentrantLock和ReadWriteLock的应用,帮助你梳理 Java 并发锁及相关的操作. ...

随机推荐

  1. Django项目后台不挂断运行

    Django项目后台不挂断运行 方法一: 1.进入项目目录下,运行下面程序: nohup python manage.py runserver 0.0.0.0:5008 & nohup(no ...

  2. 【XCTF】ics-04

    信息: 题目来源:XCTF 4th-CyberEarth 标签:PHP.SQL注入 题目描述:工控云管理系统新添加的登录和注册页面存在漏洞,请找出flag 解题过程 进入注册页面,尝试注册: 进行登录 ...

  3. easy tornado

    easy tornado 题目分析 这是一道2018年护网杯的题目 /flag.txt /welcome.txt /hints.txt 一共有3个文件. /flag.txt flag in /flll ...

  4. Spring cloud系列教程第十篇- Spring cloud整合Eureka总结篇

    Spring cloud系列教程第十篇- Spring cloud整合Eureka总结篇 本文主要内容: 1:spring cloud整合Eureka总结 本文是由凯哥(凯哥Java:kagejava ...

  5. 全栈的自我修养: 003Axios 的简单使用

    全栈的自我修养: Axios 的简单使用 You should never judge something you don't understand. 你不应该去评判你不了解的事物. 全栈的自我修养: ...

  6. jquery文件表单上传

    1. 引入jquery文件  <script src="js/jquery-2.1.1.min.js"></script> 2. 创建form表单,如下: ...

  7. tcpreplay的使用指导

    Tcpreplay的介绍 简单的说, tcpreplay是一种pcap包的重放工具, 它可以将用ethreal, wireshark工具抓下来的包原样或经过任意修改后重放回去. 它允许你对报文做任意的 ...

  8. 如何手写一个ArrayList

    写完HashMap,觉得手痒痒,所以隔了一天再来实现一下简单的ArrayList,ArrayList相比而言就非常的简单,主要的核心点有以下几个方面: 1.ArrayList的底层是由数组构成的 2. ...

  9. 随笔java面试基础

    转:http://blog.csdn.net/wenwen360360/article/details/54969418 Application ―Java应用程序”是可以独立运行的Java程序.由J ...

  10. Linux下Storm2.1.0的伪分布式安装

    官方下载网址:http://storm.apache.org/downloads.html 1.第一步我们先从官网下载解压包  2.然后进行解压 3.配置环境变量 在profile里面插入如下格式语句 ...