偏向锁

偏向锁是JDK6中的重要引进,因为HotSpot作者经过研究实践发现,在大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得,为了让线程获得锁的代价更低,引进了偏向锁。

偏向锁是在单线程执行代码块时使用的机制,如果在多线程并发的环境下(即线程A尚未执行完同步代码块,线程B发起了申请锁的申请),则一定会转化为轻量级锁或者重量级锁。

引入偏向锁主要目的是:为了在没有多线程竞争的情况下尽量减少不必要的轻量级锁执行路径。因为轻量级锁的加锁解锁操作是需要依赖多次CAS原子指令的,而偏向锁只需要在置换ThreadID的时候依赖一次CAS原子指令(一旦出现多线程竞争锁的情况就必须撤销偏向锁或者升级为轻量级锁)。

轻量级锁

引入轻量级锁的主要目的是,在多线程竞争不激烈的情况下,减少传统的重量级锁使用操作系统互斥量产生的性能消耗。当关闭偏向锁功能或者多个线程竞争偏向锁导致偏向锁升级为轻量级锁,则会尝试获取轻量级锁,其步骤如下:

  1. 在线程进入同步块时,如果同步对象锁状态为无锁状态(锁标志位为“01”状态,是否为偏向锁为“0”),虚拟机首先将在当前线程的栈帧中建立一个名为锁记录(Lock Record)的空间,用于存储锁对象目前的Mark Word的拷贝,官方称之为 Displaced Mark Word。
  2. 拷贝对象头中的Mark Word复制到锁记录(Lock Record)中;
  3. 拷贝成功后,虚拟机将使用CAS操作尝试将对象Mark Word中的Lock Word更新为指向当前线程锁记录的指针,并将锁记录里的owner指针指向锁对象mark word。
  4. 如果更新成功,说明当前线程就拥有了该对象的锁,并且将对象Mark Word的锁标志位设置为“00”,即表示此对象处于轻量级锁定状态。如果更新失败,说明存在锁竞争,就会通过自旋来尝试获取锁,当自旋达到一定的次数仍没有获取锁,说明对锁的竞争比较激烈,就会升级为重量级锁。

重量级锁

重量级锁是通过竞争一个monitor对象的所有权实现的。每一个对象都有一个monitor对象(监视器)与之关联,当一个对象的monitor被持有后,该对象就处于锁定状态。

Synchronized实现同步代码块

Synchronized实现同步代码块时,是通过mointorenter和monitorexit指令实现的,编译之后的同步代码块被包裹在mointorenter和monitorexit指令之间。

线程执行monitorenter指令时尝试获取monitor的所有权,

  • 如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者;
  • 如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1;
  • 如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权;

执行monitorexit的线程必须是所对应的monitor的所有者。指令执行时,monitor的进入数减1,如果减1后进入数为0,那线程退出monitor,不再是这个monitor的所有者。其他被这个monitor阻塞的线程可以尝试去获取这个 monitor 的所有权。注意,monitorexit指令出现了两次,第1次为同步正常退出释放锁;第2次为发生异步退出释放锁;

Synchronized实现同步方法

当调用方法时,调用指令将会检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。

同步代码块和同步方法,两种同步方式本质上没有区别,都是通过获取monitor实现。只是方法的同步是一种隐式的方式来实现,无需通过字节码来完成。两个指令的执行是JVM通过调用操作系统的互斥原语mutex来实现,被阻塞的线程会被挂起、等待重新调度,会导致“用户态和内核态”两个态之间来回切换,对性能有较大影响。

面试:Synchronized锁升级(理解)相关推荐

  1. 存储过程没有执行完后没有释放锁_【大厂面试07期】说一说你对synchronized锁的理解?...

    PS:本文已收录到1.3 K+ Star 数的开源项目-<大厂面试指北>,如果想要了解更多,可以看一看,项目地址如下: https://github.com/NotFound9/inter ...

  2. Synchronized锁升级:无锁-> 偏向锁 -> 轻量级锁 -> 重量级锁

    一. 概述 1. Synchronized锁升级的原因 用锁能够实现数据的安全性,但是会带来性能下降.无锁能够基于线程并行提升程序性能,但是会带来安全性下降. 2. Synchronized锁升级的过 ...

  3. Synchronized 锁升级机制

    在 JDK 早期的版本,synchronized 锁的效率是非常低的,它的效率远低于 lock 锁,但是 sychronized 毕竟是 java 的关键词,它不应该就此淘汰.所以在 JDK1.6 中 ...

  4. 22-10-14 西安 spring循环依赖、对象内存布局、synchronized锁升级

    关于锁升级参考了周阳老师在b站的juc视频,阳哥讲的很好 尚硅谷2022版JUC并发编程(对标阿里P6-P7)_哔哩哔哩_bilibili spring循环依赖 1.循环依赖问题 什么是循环依赖 默认 ...

  5. Synchronized锁升级、降级

    多线程中锁的升级 synchronized锁升级原理:在锁对象的对象头里面有一个threadid字段,在第一次访问的时候threadid为空,jvm 让其持有偏向锁,并将threadid 设置为其线程 ...

  6. synchronized锁升级过程及其实现原理

    本文链接:https://blog.csdn.net/wangyy130/article/details/106495180 问:为什么会有锁升级的过程呢 答:在java6以前synchronized ...

  7. synchronized 锁升级过程

    synchronized 锁升级过程就是其优化的核心:偏向锁 -> 轻量级锁 -> 重量级锁 class Test{private static final Object object = ...

  8. synchronized锁升级过程详解

    32位: 64位: 无锁: 1001001110000101111101010101110 HashCode:1237514926 十进制:1237514926 二进制:0100100 1100001 ...

  9. Synchronized锁升级底层原理

    思考问题 首先请您思考下面的问题: Synchronized锁同步机制性能不好嘛? 一个对象天生对应一个monitor锁吗? 为什么说synchronized是非公平锁? synchronized字节 ...

  10. synchronized锁升级_synchronized详解以及锁的膨胀升级过程

    点击上方"码之初"关注,···选择"设为星标" 与精品技术文章不期而遇 来源:www.cnblogs.com/cxiaocai/p/12189848.html ...

最新文章

  1. JQuery开发之Galleriffic图片插件介绍
  2. Java高并发编程:取消和关闭
  3. boost::search_n相关的测试程序
  4. JAVA输出希腊union,希腊文化认为,最为抽象的艺术形式是()。
  5. 阿里多语言翻译模型的前沿探索及技术实践
  6. Help Me Escape
  7. [题解] 2038: [2009国家集训队]小Z的袜子(hose)
  8. 关于等价鞅、反等价鞅、剀利公式、赌徒输光定理
  9. 阿里云商标注册申请智能、顾问和安心区别及选择攻略
  10. 老九学堂 学习 C++ 第五天
  11. Protel (DXP2004sp2) 许可协议认证过程
  12. linux格式化sd卡,并进行挂载
  13. sun.misc.BASE64Encoder是内部专用 API, 可能会在未来发行版中删除
  14. 与Lucene 4.10配合的中文分词比较(转)
  15. 《穷查理宝典》思维导图
  16. 推荐一款看书学习必备的读书笔记app
  17. Convex Optimization
  18. RIM Hong Kong地址和地图
  19. 备战sp23春招 day8 | 344.反转字符串 541. 反转字符串II 剑指 05.替换空格 151.翻转字符串里的单词 剑指58-II.左旋转字符串
  20. pycharm解决光标变粗,关闭改写模式

热门文章

  1. sql查询慢原因及优化
  2. 玩音响发烧友必看的博客
  3. CMS3.0——初次邂逅express
  4. 解决 Exchange 2013提示“出现意外错误,无法处理您的请求”,无法打开OWA和ECP...
  5. 打靶(递归算法) | 八皇后(回溯算法)
  6. ERROR 1201 (HY000) Could not initialize master info structure
  7. spring源码学习(1)- bean
  8. visual studio 2010 c++ 打印 Hello world
  9. JQ 按钮实现两种功能
  10. shell脚本命令行参数里的空白符