JUC:Synchronized和锁升级

news2025/1/19 17:22:05

1. 面试题

  • 谈谈你对Synchronized的理解
  • Sychronized的锁升级你聊聊
  • Synchronized实现原理,monitor对象什么时候生成的?知道monitor的monitorenter和monitorexit这两个是怎么保证同步的嘛?或者说这两个操作计算机底层是如何执行的
  • 偏向锁和轻量级锁有什么区别

2. Synchronized的性能变化

  • Java5以前,只有Synchronized,这个是操作系统级别的重量级操作
    • 重量级锁,假如锁的竞争比较激烈的话,性能下降
    • Java 5之前 用户态和内核态之间的转换
  • Java6 之后为了减少获得锁和释放锁所带来的性能消耗,引入了轻量级锁和偏向锁

3. synchronized锁种类和升级步骤

3.1 多线程访问情况

  • 只有一个线程来访问,有且唯一Only One
  • 有两个线程(2个线程交替访问)
  • 竞争激烈,更多线程来访问

3.2 升级流程

  • Synchronized用的锁是存在Java对象头里的MarkWord中,锁升级功能主要依赖MarkWord中锁标志位和释放偏向锁标志位
  • 锁指向,请牢记
    • 偏向锁:MarkWord存储的是偏向的线程ID
    • 轻量锁:MarkWord存储的是指向线程栈中Lock Record的指针
    • 重量锁:MarkWord存储的是指向堆中的monitor对象(系统互斥量指针)

 3.3 无锁

3.4 偏向锁

偏向锁:单线程竞争,当线程A第一次竞争到锁时,通过修改MarkWord中的偏向线程ID、偏向模式。如果不存在其他线程竞争,那么持有偏向锁的线程将永远不需要进行同步。

主要作用:

  • 当一段同步代码一直被同一个线程多次访问,由于只有一个线程那么该线程在后续访问时便会自动获得锁
  • 同一个老顾客来访,直接老规矩行方便

结论:

  • HotSpot的作者经过研究发现,大多数情况下:在多线程情况下,锁不仅不存在多线程竞争,还存在由同一个线程多次获得的情况,偏向锁就是在这种情况下出现的,它的出现是为了解决只有一个线程执行同步时提高性能。
  • 偏向锁会偏向于第一个访问锁的线程,如果在接下来的运行过程中,该锁没有被其他线程访问,则持有偏向锁的线程将永远不需要出发同步。也即偏向锁在资源在没有竞争情况下消除了同步语句,懒得连CAS操作都不做了,直接提高程序性能。

理论落地:

技术实现:

偏向锁JVM命令:

案例演示:

  • 偏向锁默认情况演示---只有一个线程

public class SynchronizedUpDemo {

    public static void main(String[] args) {
        /**
         * 这里偏向锁在JDK6以上默认开启,开启后程序启动几秒后才会被激活,可以通过JVM参数来关闭延迟 -XX:BiasedLockingStartupDelay=0
         */
//        try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }
        Object o = new Object();
        synchronized (o) {
            System.out.println(ClassLayout.parseInstance(o).toPrintable());
        }
    }
}

 

偏向锁的撤销:

  • 当有另外一个线程逐步来竞争锁的时候,就不能再使用偏向锁了,要升级为轻量级锁,使用的是等到竞争出现才释放锁的机制
  • 竞争线程尝试CAS更新对象头失败,会等到全局安全点(此时不会执行任何代码)撤销偏向锁,同时检查持有偏向锁的线程是否还在执行:
    • 第一个线程正在执行Synchronized方法(处于同步块),它还没有执行完,其他线程来抢夺,该偏向锁会被取消掉并出现锁升级,此时轻量级锁由原来持有偏向锁的线程持有,继续执行同步代码块,而正在竞争的线程会自动进入自旋等待获得该轻量级锁
    • 第一个线程执行完Synchronized(退出同步块),则将对象头设置为无所状态并撤销偏向锁,重新偏向。

题外话:Java15以后逐步废弃偏向锁,需要手动开启------->维护成本高

3.5 轻量锁

概念:多线程竞争,但是任意时候最多只有一个线程竞争,即不存在锁竞争太激烈的情况,也就没有线程阻塞。

主要作用:有线程来参与锁的竞争,但是获取锁的冲突时间极短---------->本质是自旋锁CAS

轻量锁的获取:

案例演示:

自旋一定程度和次数(Java8 之后是自适应自旋锁------意味着自旋的次数不是固定不变的):

  • 线程如果自旋成功了,那下次自旋的最大次数会增加,因为JVM认为既然上次成功了,那么这一次也大概率会成功
  • 如果很少会自选成功,那么下次会减少自旋的次数甚至不自旋,避免CPU空转

轻量锁和偏向锁的区别:

  • 争夺轻量锁失败时,自旋尝试抢占锁
  • 轻量级锁每次退出同步块都需要释放锁,而偏向锁是在竞争发生时才释放锁

 3.5 重量锁

有大量线程参与锁的竞争,冲突性很高

3.6 小结

 

  • 锁升级的过程

  • 锁升级后,hashcode去哪儿了?
  • 各种锁优缺点、synchronized锁升级和实现原理

4. JIT编译器对锁的优化

4.1 锁消除

/**
 * 锁消除
 * 从JIT角度看想相当于无视他,synchronized(o)不存在了
 * 这个锁对象并没有被共用扩散到其他线程使用
 * 极端的说就是根本没有加锁对象的底层机器码,消除了锁的使用
 */
public class LockClearUpDemo {
    static Object object = new Object();

    public void m1() {
        //锁消除问题,JIT会无视它,synchronized(o)每次new出来的,都不存在了,非正常的
        Object o = new Object();
        synchronized (o) {
            System.out.println("-----------hello LockClearUpDemo" + "\t" + o.hashCode() + "\t" + object.hashCode());
        }
    }

    public static void main(String[] args) {
        LockClearUpDemo lockClearUpDemo = new LockClearUpDemo();
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                lockClearUpDemo.m1();
            }, String.valueOf(i)).start();
        }
    }
}
/**
 * -----------hello LockClearUpDemo	229465744	57319765
 * -----------hello LockClearUpDemo	219013680	57319765
 * -----------hello LockClearUpDemo	1109337020	57319765
 * -----------hello LockClearUpDemo	94808467	57319765
 * -----------hello LockClearUpDemo	973369600	57319765
 * -----------hello LockClearUpDemo	64667370	57319765
 * -----------hello LockClearUpDemo	1201983305	57319765
 * -----------hello LockClearUpDemo	573110659	57319765
 * -----------hello LockClearUpDemo	1863380256	57319765
 * -----------hello LockClearUpDemo	1119787251	57319765
 */

 4.2 锁粗化

/**
 * 锁粗化
 * 假如方法中首尾相接,前后相邻的都是同一个锁对象,那JIT编译器会把这几个synchronized块合并为一个大块
 * 加粗加大范围,一次申请锁使用即可,避免次次的申请和释放锁,提高了性能
 */
public class LockBigDemo {
    static Object objectLock = new Object();

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (objectLock) {
                System.out.println("111111111111");
            }
            synchronized (objectLock) {
                System.out.println("222222222222");
            }
            synchronized (objectLock) {
                System.out.println("333333333333");
            }
            synchronized (objectLock) {
                System.out.println("444444444444");
            }
            //底层JIT的锁粗化优化
            synchronized (objectLock) {
                System.out.println("111111111111");
                System.out.println("222222222222");
                System.out.println("333333333333");
                System.out.println("444444444444");
            }
        }, "t1").start();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2255958.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SAP SD学习笔记19 - 形式发票(Proforma Invoice)

上面几章讲了投诉处理。 SAP SD学习笔记18 - 投诉处理4 - 请求书订正依赖&#xff0c;投诉处理流程的总结-CSDN博客 本章继续学习SD 模块的其他内容。 本章讲了形式发票&#xff08;Proforma Invoice&#xff09;的概要及系统操作。 形式发票是在出库确认之前&#xff0c;有…

M005 PHP+MYSQL+web编程课程网站的设计与实现 源码 配置 文档

web编程课程网站 1.摘要2.开发目的和意义3.系统功能设计4.系统界面截图5.源码获取 1.摘要 随着互联网的飞速发展&#xff0c;各行各业的信息化进程逐步加快。商业信息化、政务信息化、教育信息、服务信息化等等已遍布全国各地。信息化的服务平台能更加高效的为用户提供各种服务…

【力扣】13.罗马数字转整数

问题描述 思路解析 对于这种限制字符的问题&#xff0c;使用Map来对键值存储 对其进行判断&#xff0c;如果前面的数小于后面的数&#xff0c;那么结果相减 否则&#xff0c;正常相加。 代码 class Solution {Map<Character,Integer> mapnew HashMap<Character,In…

docker安装ddns-go(外网连接局域网)

docker先下载镜像&#xff0c;目前最新版是v6.7.6 也可以csdn资源下载 再导入dockers https://download.csdn.net/download/u014756339/90096748 docker load -i ddns-go.tar 启动 docker run -d --name ddns-go --restartalways --nethost -v /opt/ddns-go:/root jeessy/…

洛谷P4913 【深基16.例3】二叉树深度(c嘎嘎)

题目链接&#xff1a;P4913 【深基16.例3】二叉树深度 - 洛谷 | 计算机科学教育新生态 题目难度&#xff1a;普及 解题思路&#xff1a;本题要求树的深度&#xff0c;即求左右子树高度的最大值&#xff0c;首先我们用结构体存树左右节点&#xff0c;然后分别递归地去左右子树的…

Android -- [SelfView] 自定义多行歌词滚动显示器

Android – [SelfView] 自定义多行歌词滚动显示器 流畅、丝滑的滚动歌词控件* 1. 背景透明&#xff1b;* 2. 外部可控制进度变化&#xff1b;* 3. 支持屏幕拖动调节进度&#xff08;回调给外部&#xff09;&#xff1b;效果 歌词文件&#xff08;.lrc&#xff09; 一. 使用…

DNS/域名

概述 每个应用层协议都是为了解决某一类应用问题&#xff0c;而问题的解决又往往是通过位于不同主机中的多个应用进程之间的通信和协同工作来完成的。应用层的具体内容就是规定应用进程在通信时所遵循的协议。 应用层的许多协议都是基于客户服务器方式。客户(client)和服务器…

淘宝直播间智能化升级:基于LLM的学习与分析

自营直播应用技术团队负责的业务中&#xff0c;淘宝买菜的直播业务起步较晚&#xff0c;业务发展压力较大&#xff0c;业务上也就有了期望能够对一些二方的标杆直播间进行学习&#xff0c;并将其优点应用到自己直播间的需求。 最初 - 人海战术&#xff0c;学习PK 业务侧最直接的…

数学拯救世界(一)———寻“数”记

一、 很久很久以前&#xff0c;在一个只认识整数和小数的国度&#xff0c;有一个很残暴的国王提了一个要求&#xff1a;要是不能表示出把一段1米的绳子三等分后的大小&#xff0c;就要把所有的大臣杀掉。 1➗3 0.333&#xff0c;怎么办呀&#xff1f;怎么办呀&#xff1f; 袁q…

夏普MX-4608N复印机维修模式进入方法及载体初始化方法

夏普MX-4608N复印机载体型号&#xff08;图&#xff09;&#xff1a; 型 号&#xff1a;载体&#xff08;黑色&#xff09;MX-561CV 净含量&#xff1a;395克 下面图片中分别有载体、刮板、鼓芯、上纸盒搓纸轮一套&#xff0c;均原装正品&#xff1b; 保养周期将至的时候建…

FPGA Xilinx维特比译码器实现卷积码译码

FPGA Xilinx维特比译码器实现卷积码译码 文章目录 FPGA Xilinx维特比译码器实现卷积码译码1 Xilinx维特比译码器实现2 完整代码3 仿真结果 MATLAB &#xff08;n,k,m&#xff09;卷积码原理及仿真代码&#xff08;你值得拥有&#xff09;_matlab仿真后代码-CSDN博客 MATLAB 仿真…

java+ssm+mysql水产品商城

项目介绍&#xff1a; 使用javassmmysql开发的水产品商城&#xff0c;系统包含管理员、用户角色&#xff0c;功能如下&#xff1a; 管理员&#xff1a;用户管理&#xff1b;种类管理&#xff1b;商品管理&#xff1b;订单管理&#xff1b;评论管理&#xff1b;新闻管理&#…

【传感器技术】第5章 电容式传感器,变极距式电容传感器,变面积式电容传感器,变介质式电容传感器

关注作者了解更多 我的其他CSDN专栏 过程控制系统 工程测试技术 虚拟仪器技术 可编程控制器 工业现场总线 数字图像处理 智能控制 传感器技术 嵌入式系统 复变函数与积分变换 单片机原理 线性代数 大学物理 热工与工程流体力学 数字信号处理 光电融合集成电路…

二叉树前序遍历

什么是前序遍历&#xff1f; 一个二叉树的前序遍历就是对于树中的每一个节点而言&#xff0c;都是先遍历自己&#xff0c;再遍历左右。 如&#xff1a; 递归实现前序遍历 题目链接&#xff1a;144. 二叉树的前序遍历 - 力扣&#xff08;LeetCode&#xff09; 实现步骤&…

RAG系统分类、评估方法与未来方向

分享一篇RAG综述&#xff1a;Retrieval-Augmented Generation for Large Language Models: A Survey&#xff0c;主要想了解一下RAG的评估方法&#xff0c;分享给大家。 文章目录 一、RAG分类二、评估方法三、未来方向 一、RAG分类 RAG分类&#xff1a;Navie RAG、Advanced RA…

【软件安全】软件安全设计规范,软件系统安全设计制度(Word原件)

1.1安全建设原则 1.2 安全管理体系 1.3 安全管理规范 1.4 数据安全保障措施 1.4.1 数据库安全保障 1.4.2 操作系统安全保障 1.4.3 病毒防治 1.5安全保障措施 1.5.1实名认证保障 1.5.2 接口安全保障 1.5.3 加密传输保障 1.5.4终端安全保障 软件全面文档清单涵盖以下核心内容&a…

约克约克VRF中央空调,清凉舒适从此不再是梦

生活总是少不了空调的陪伴。但是&#xff0c;你是否还在为传统空调的高能耗、低效率而烦恼&#xff1f;别担心&#xff0c;约克VRF中央空调来帮你解决这一切难题&#xff01;      节能省电&#xff0c;我懂你~      现代生活讲究的是高效和环保&#xff0c;而约克VRF中…

DMA简介

DMA是一个数据转运小助手, 它主要是用来协助CPU,完成数据转运的工作 第一个程序: 在这个程序里&#xff0c;我们将使用DMA&#xff0c;进行存储器到存储器的数据转运, 也就是把一个数组里面的数据&#xff0c; 复制到另一个数组里 DMA简介 DMA外设&#xff0c; 是可以直接访…

liunx docker 部署 nacos seata sentinel

部署nacos 1.按要求创建好数据库 2.创建docker 容器 docker run -d --name nacos-server -p 8848:8848 -p 9848:9848 -p 9849:9849 -e MODEstandalone -e SPRING_DATASOURCE_PLATFORMmysql -e MYSQL_SERVICE_HOST172.17.251.166 -e MYSQL_SERVICE_DB_NAMEry-config -e MYSQL…

计算机视觉与各个学科融合:探索新方向

目录 引言计算机视觉与其他学科的结合 与医学的结合与机械工程的结合与土木工程的结合与艺术与人文的结合发文的好处博雅知航的辅导服务 引言 计算机视觉作为人工智能领域的重要分支&#xff0c;正迅速发展并渗透到多个学科。通过与其他领域的结合&#xff0c;计算机视觉不仅…