首页 > 其他分享 >面试官:小伙子知道synchronized的优化过程吗?我:嘚吧嘚吧嘚,面试官:出去!

面试官:小伙子知道synchronized的优化过程吗?我:嘚吧嘚吧嘚,面试官:出去!

时间:2024-03-24 22:35:34浏览次数:22  
标签:面试官 synchronized 对象 小伙子 线程 轻量级 偏向

写在开头

面试官:小伙子,多线程中锁用过吗?
我:那是自然!
面试官:那你知道synchronized的优化吗?
我:synchronized作为重锁,开销大,在早期不被推荐使用,后期进行了优化,至于怎么优化的话,您让我想想哈...
面试官:好的,那你出去好好想吧!

对于synchronized的优化,虽然被问到的场景不多,但在很多网友发的面经中发现很多人都会挂在这个点上。

在我们初学锁时,很多人可能都觉得它是一个重量级锁,代码中不建议使用,但其实现如今经过了层层优化后,synchronized被广泛的应用在了JVM源码以及众多开源框架中,我们今天就来一起学习一下synchronized的优化过程!

对象锁的四种状态

首先,我们这里要记住一个Java迭代版本JDK1.6,这个版本对于synchronized来说是划时代的,在此之前,synchronized确实是一种重量级悲观锁,这个时候的它使用起来极耗资源,为所有高效开发者所弊病,但在1.6版本之后,引入了“偏向锁”和“轻量级锁” 的概念,这极大减少了获取synchronized锁和释放锁所需资源,synchronized重获新生!

在此之后,对象的锁便拥有了4种状态,根据锁的级别从低到高可分为:

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

无锁

无锁其实很好理解,就是没有对共享资源进行任何锁定,所有线程都可以去访问并修改同一资源,但同时只能有一个线程修改成功,其他线程不断尝试直至成功,并会将原内容覆盖。

偏向锁

偏向锁,指的就是偏向第一个加锁线程,对象的代码一直被同一线程执行,不存在多个线程竞争,该线程在后续的执行中自动获取锁,降低获取锁带来的性能开销。

轻量级锁

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

重量级锁

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

重量级锁通过对象内部的监视器(monitor)实现,而其中 monitor 的本质是依赖于底层操作系统的 Mutex Lock 实现,操作系统实现线程之间的切换需要从用户态切换到内核态,切换成本非常高。所以在没有被优化之前,synchronized这种重量级锁,才不受重视!
image

对象锁的存储

学习完对象锁的四种状态后,我们继续思考下一个问题,既然对象锁有四种状态,那它们是存储在哪里的呢?

会联想的同学,我想已经猜出了大概,首先在Java中的锁都是基于对象的,既然基于对象,那它存在的地方大概率要在对象中,而我们知道在JVM中,对象分为三个部分对象头、实例数据、字节对齐,其中对象头又由Mark Word和Klass Point构成,而Mark Word(标记字段)用于存储对象自身的运行时数据,例如存储对象的HashCode,分代年龄、锁标志位等信息,是synchronized实现轻量级锁和偏向锁的关键。我们64位虚拟机为例看下图:
image

当对象状态是偏向锁时,MarkWord中存储了偏向线程的ID,并且将是否偏向标志置为1;当对象状态是轻量级锁时,Mark Word存储的是指向线程栈中Lock Record的指针;当状态为重量级锁时,Mark Word为指向monitor(监视器)对象的指针。

synchronized 锁升级的过程

有了上面的知识储备,我们趁着打铁,来聊一聊synchronized 锁升级的过程,由低到高,逐渐升级。
1️⃣首先,在锁对象的对象头里面有一个 threadid 字段,未访问时 threadid 为空,这时是无锁状态,任何线程都可竞争获取共享资源;
2️⃣ 先得到共享资源的线程,其线程ID会被记录到Mark Word中,此时锁状态为偏向锁;
3️⃣ 当后续还有线程去获取共享资源时,会先判断 threadid 是否与其线程 id 一致。如果一致则可以直接使用此对象;如果不一致,则升级偏向锁为轻量级锁,通过自旋循环一定次数来获取锁;
4️⃣自旋的线程在自旋过程中,成功获得资源(即之前获的资源的线程执行完成并释放了共享资源),则整个状态依然处于 轻量级锁的状态,如果自旋失败 。
5️⃣进入重量级锁的状态,这个时候,自旋的线程进行阻塞,等待之前线程执行完成并唤醒自己。

结尾彩蛋

如果本篇博客对您有一定的帮助,大家记得留言+点赞+收藏呀。原创不易,转载请联系Build哥!

image

如果您想与Build哥的关系更近一步,还可以关注“JavaBuild888”,在这里除了看到《Java成长计划》系列博文,还有提升工作效率的小笔记、读书心得、大厂面经、人生感悟等等,欢迎您的加入!

image

标签:面试官,synchronized,对象,小伙子,线程,轻量级,偏向
From: https://www.cnblogs.com/JavaBuild/p/18093221

相关文章

  • 设计模式-单例模式(模拟面试官八股)
    一、请说下设计模式中,你熟悉的设计模式单例模式二、单例模式你有了解吗单例模式是创建型设计模式,该类负责创建自己的对象,他确保一个类只有一个实例,并且提拱了一个去全局访问点来访问该实例。二、单例模式有几种实现方式 1.饿汉式(静态常量)优点:写法容易,在类加载的时候就......
  • 是时候来唠一唠synchronized关键字了,Java多线程的必问考点!
    写在开头在之前的博文中,我们介绍了volatile关键字,Java中的锁以及锁的分类,今天我们花5分钟时间,一起学习一下另一个关键字:synchronized。synchronized是什么?首先synchronized是Java中的一个关键字,所谓关键字,就是Java中根据底层封装所赋予的一种具有特殊语义的单词,而synchronized......
  • Java中的synchronized关键字是如何工作的?
    在Java中,synchronized关键字是一种内置的同步机制,用于控制多个线程对共享资源的访问,以防止出现数据不一致和竞态条件。当一个线程进入一个synchronized块或方法时,它需要获取一个锁(也称为监视器锁或互斥锁),如果锁已经被其他线程持有,则该线程将被阻塞,直到锁被释放。以下是sync......
  • Synchronized的底层实现原理(转载)
    synchronized一.synchronized解读1.1简单描述synchronized关键字解决的是多个线程之间访问资源的同步性,synchronized翻译为中文的意思是同步,也称之为同步锁。synchronized的作用是保证在同一时刻,被修饰的代码块或方法只会有一个线程执行,以达到保证并发安全的效果。1.2特性......
  • 面试官:Kafka和ES选主有什么区别?
    Kafka和ES都是用来处理大数据的中间件,一个是消息中间件的代表(Kafka),另一个是大数据搜索引擎的代表(ES)。它们在Java领域的使用非常广泛,在大数据方面就更不用说了,但它们的选主(选择主节点)有什么关联与区别呢?接下来,我们一起来看。1.基础概念1.1什么是Kafka?Kafka是一个分布式......
  • 为什么面试官都爱问websocket?
    什么是webSocket?WebSocket是一种在单个TCP连接上进行全双工通信的应用层协议,它弥补HTTP协议在持久通信能力上的不足,允许服务器主动向客户端推送数据,并且简化了客户端和服务器之间的数据交换。在WebSocket通讯中,浏览器和服务器只需完成一次握手,便可创建持久性连接。Web......
  • 今天去面试,面试官问我什么是容器编排工具?Kubernetes
    今天去面试,面试官问我什么是容器编排工具?KubernetesKubernetes(简称k8s)是一个开源的容器编排平台,用于自动化应用程序部署、扩展和管理。它提供了一种高效的方式来管理容器化应用程序,使得开发人员和运维人员可以更好地协同工作。本文将介绍Kubernetes的集群架构和组件,并通过......
  • 面试官:volatile如何保证可见性的,具体如何实现?
    写在开头在之前的几篇博文中,我们都提到了volatile关键字,这个单词中文释义为:不稳定的,易挥发的,在Java中代表变量修饰符,用来修饰会被不同线程访问和修改的变量,对于方法,代码块,方法参数,局部变量以及实例常量,类常量多不能进行修饰。自JDK1.5之后,官网对volatile进行了语义增强,这让它......
  • 面试官:SpringBoot如何优雅停机?
    优雅停机(GracefulShutdown)是指在服务器需要关闭或重启时,能够先处理完当前正在进行的请求,然后再停止服务的操作。优雅停机的实现步骤主要分为以下几步:停止接收新的请求:首先,系统会停止接受新的请求,这样就不会有新的任务被添加到任务队列中。处理当前请求:系统会继续处理当前已......
  • Java中的synchronized
    概述Java的锁可以分为乐观锁和悲观锁两类。而synchronized是悲观锁的代表。本文想要说明一下两个问题:synchronized锁的是哪个对象publicvoidmethod(){ synchronized(this){ ... }}publicsynchronizedvoidmethod(){ ...}    上述两种方式,synchronize......