热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JDK1.6对synchronized的锁优化

jdk1,6,对,synchroni
  1. 背景

在 JDK 1.6 中对锁的实现引入了大量的优化。

目的

减少锁操作的开销。

  1. 锁优化

在看下面的内容之间,希望大家对 Mark Word 有个大体的理解。Java 中一个对象在堆中的内存结构是这样的:

Mark Word 是这样的:

2.1 适应性自旋锁

自旋锁的思想: 让一个线程在请求一个共享数据的锁时执行忙循环(自旋)一段时间,如果在这段时间内能获得锁,就可以 避免进入阻塞状态 。

自旋锁的缺点: 需要进行忙循环操作 占用 CPU 时间 ,它只适用于 共享数据的锁定状态很短的场景 。

若锁被其他线程长时间占用,会带来许多性能上的开销。所以自旋的次数不再固定。由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。

如果共享数据的锁定状态持续时间较短,切换线程不值得(会有上下文切换),可以利用自旋锁尝试一定的次数。

2.2 锁消除

JIT 编译时,会去除不可能存在竞争的锁。通过 JIT 的逃逸分析 来 消除一些没有在当前同步块以外被其他线程共享的数据的锁的保护 ,通过逃逸分析在 TLAB 来分配对象,这样就不存在共享数据带来的线程安全问题。

2.3 锁粗化

减少不必要的紧连在一起的 lock,unlock 操作, 将多个连续的锁扩展成一个范围更大的锁 。

2.4 偏向锁(重入锁)

为了在无线程竞争的情况下避免在锁获取过程中执行不必要的 CAS 原子指令,因为 CAS 原子指令虽然相对于重量级锁来说开销比较小但还是存在非常可观的本地延迟(因为 C AS 的底层是利用 LOCK 指令 + cmpxchg 汇编指令来保证原子性的 ,LOCK 指令会锁总线,其他 CPU 的内存操作将会被阻塞,因为 CPU 架构如果是 CMU 的话,控制信号、数据信号等是通过共享总线传到内存控制器中)。减少同一线程获取锁的代价,省去了大量有关 锁申请 的操作。

核心思想

如果一个线程获得了锁, 那么锁就进入偏向模式,此时 Mark Word 的结构也变为偏向锁结构,当该线程再次请求锁时,无需再做任何同步操作,即 获取锁的过程只需要检查 Mark Word 的锁标记位为偏向锁以及当前线程 Id 等于 Mark Word 的 ThreadId 即可,这样就 省去了大量有关锁申请的操作 。

2.5 轻量级锁

这种锁实现的背后基于这样一种假设,即在真实的情况下我们程序中的大部分同步代码一般都处于无锁竞争状态(即单线程执行环境),在无锁竞争的情况下完全可以 避免调用操作系统层面的重量级互斥锁 (重量级锁的底层就是这样实现的),只需要依靠一条 CAS 原子指令就可以完成锁的获取及释放。 当存在锁竞争的情况下,执行 CAS 指令失败的线程将调用操作系统互斥锁进入到阻塞状态,当锁被释放的时候被唤醒。

2.5.1 加锁的过程

主要分为 3 步:

1、在线程进入同步块的时候,如果同步对象状态为 无锁状态 (锁标志为 01), 虚拟机首先将在当前线程的栈帧中建立一个名为锁记录的空间,用来存储锁对象目前的 Mark Word 的拷贝 。拷贝成功后,虚拟机将使用 CAS 操作尝试将对象的 Mark Word 更新为指向 Lock Record 的指针,并将 Lock Record 里的 owner 指针指向锁对象的 Mark Word。如果更新成功,则执行 2,否则执行 3。

2、如果这个更新动作成功了,那么这个线程就拥有了该对象的锁,并且锁 对象的 Mark Word 中的锁标志位设置为 "00" ,即表示此对象处于轻量级锁定状态,这时候虚拟机线程栈与堆中锁对象的对象头的状态如图所示。

3、如果这个更新操作失败了,虚拟机首先会检查锁对象的 Mark Word 是否指向当前线程的栈帧,如果是就说明当前线程已经拥有了这个对象的锁,那就可以直接进入同步块继续执行。否则说明多个线程竞争锁,轻量级锁就要膨胀为重要量级锁,锁标志的状态值变为 "10",Mark Word 中存储的就是指向重量级锁的指针,后面等待锁的线程也要进入阻塞状态。而当前线程便尝试使用自旋来获取锁。 自旋失败后膨胀为重量级锁 ,被阻塞。

2.5.2 解锁的过程

因为虚拟机线程栈帧中的 Displaced Mark Word 是最初的无锁状态时的数据结构,所以用它来替换对象头中的 Mark Word 就可以释放锁。如果锁已经膨胀为重量级,此时是不可以被替换的,所以替换失败,唤醒被挂起的线程。

  1. 心得

锁膨胀的过程

其实就是对象头中的 Mark Word 数据结构改变的过程。

  1. 三种锁的对比

4.1 偏向锁

只需要判断 Mark Word 中的一些值是否正确就行。

只有一个线程访问同步块时,使用偏向锁。

4.2 轻量级锁

需要执行 CAS 操作自旋来获取锁。

如果执行同步块的时间比较少,那么多个线程之间执行使用轻量级锁交替执行。

4.3 重量级锁

会发生上下文切换,CPU 状态从用户态转换为内核态执行操作系统提供的互斥锁,所以系统开销比较大,响应时间也比较缓慢。

如果执行同步块的时间比较长,那么多个线程之间刚开始使用轻量级锁,后面膨胀为重量级锁。(因为执行同步块的时间长,线程 CAS 自旋获得轻量级锁失败后就会锁膨胀)

  1. 总结

需要java学习路线图的私信笔者“java”领取哦!另外喜欢这篇文章的可以给笔者点个赞,关注一下,每天都会分享Java相关文章!还有不定时的福利赠送,包括整理的学习资料,面试题,源码等~~


推荐阅读
  • 浏览器作为我们日常不可或缺的软件工具,其背后的运作机制却鲜为人知。本文将深入探讨浏览器内核及其版本的演变历程,帮助读者更好地理解这一关键技术组件,揭示其内部运作的奥秘。 ... [详细]
  • 兆芯X86 CPU架构的演进与现状(国产CPU系列)
    本文详细介绍了兆芯X86 CPU架构的发展历程,从公司成立背景到关键技术授权,再到具体芯片架构的演进,全面解析了兆芯在国产CPU领域的贡献与挑战。 ... [详细]
  • 2020年9月15日,Oracle正式发布了最新的JDK 15版本。本次更新带来了许多新特性,包括隐藏类、EdDSA签名算法、模式匹配、记录类、封闭类和文本块等。 ... [详细]
  • 应用链时代,详解 Avalanche 与 Cosmos 的差异 ... [详细]
  • Java高并发与多线程(二):线程的实现方式详解
    本文将深入探讨Java中线程的三种主要实现方式,包括继承Thread类、实现Runnable接口和实现Callable接口,并分析它们之间的异同及其应用场景。 ... [详细]
  • 秒建一个后台管理系统?用这5个开源免费的Java项目就够了
    秒建一个后台管理系统?用这5个开源免费的Java项目就够了 ... [详细]
  • 本文整理了一份基础的嵌入式Linux工程师笔试题,涵盖填空题、编程题和简答题,旨在帮助考生更好地准备考试。 ... [详细]
  • 高端存储技术演进与趋势
    本文探讨了高端存储技术的发展趋势,包括松耦合架构、虚拟化、高性能、高安全性和智能化等方面。同时,分析了全闪存阵列和中端存储集群对高端存储市场的冲击,以及高端存储在不同应用场景中的发展趋势。 ... [详细]
  • 本文详细介绍了Java反射机制的基本概念、获取Class对象的方法、反射的主要功能及其在实际开发中的应用。通过具体示例,帮助读者更好地理解和使用Java反射。 ... [详细]
  • 本文将带你快速了解 SpringMVC 框架的基本使用方法,通过实现一个简单的 Controller 并在浏览器中访问,展示 SpringMVC 的强大与简便。 ... [详细]
  • 本文介绍了在 Java 编程中遇到的一个常见错误:对象无法转换为 long 类型,并提供了详细的解决方案。 ... [详细]
  • 本文总结了一些开发中常见的问题及其解决方案,包括特性过滤器的使用、NuGet程序集版本冲突、线程存储、溢出检查、ThreadPool的最大线程数设置、Redis使用中的问题以及Task.Result和Task.GetAwaiter().GetResult()的区别。 ... [详细]
  • 单片机入门指南:基础理论与实践
    本文介绍了单片机的基础知识及其应用。单片机是一种将微处理器(类似于CPU)、存储器(类似硬盘和内存)以及多种输入输出接口集成在一块硅片上的微型计算机系统。通过详细解析其内部结构和功能,帮助初学者快速掌握单片机的基本原理和实际操作方法。 ... [详细]
  • 本文通过思维导图的形式,深入解析了大型网站技术架构的核心原理与实际案例。首先,探讨了大型网站架构的演化过程,从单体应用到分布式系统的转变,以及各阶段的关键技术和挑战。接着,详细分析了常见的大型网站架构模式,包括负载均衡、缓存机制、数据库设计等,并结合具体案例进行说明。这些内容不仅有助于理解大型网站的技术实现,还能为实际项目提供宝贵的参考。 ... [详细]
  • Juval Löwy主张,每个类都应被视为服务,这并非是为了让服务无处不在,而是因为微服务是经过深思熟虑后系统分解的自然结果。在他的设计和构建的系统中,这种理念有助于提高模块化、可维护性和扩展性。通过将每个类视为独立的服务,系统能够更好地应对复杂性,实现更灵活的部署和更高的性能。 ... [详细]
author-avatar
J_ai糖
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有