从MESA模型到锁升级:synchronized性能逆袭的底层逻辑

news/2025/9/27 1:09:07/文章来源:https://www.cnblogs.com/poemyang/p/19110705

从MESA模型到锁升级:synchronized性能逆袭的底层逻辑

管程(Monitor)是一种用于管理共享资源访问的程序结构,能确保同一时刻只有一个线程访问共享资源,解决并发编程中的互斥和同步问题。MESA模型是管程的经典实现,主要由入口等待队列和条件变量等待队列构成。
1)入口等待队列‌:确保线程互斥,多个线程试图进入管程时,仅一个线程能成功,其余线程在入口等待队列中排队。
2)条件变量等待队列‌:解决线程同步问题,线程在管程内执行时,若条件不满足需等待其他线程操作结果,则进入相应条件变量的等待队列。
当线程被notify或notifyAll唤醒后,不会立即执行,而是先进入入口等待队列竞争管程的锁。只有竞争到锁后,线程才能继续执行。因此,被唤醒的线程需循环检验条件是否满足,即采用while (条件不满足) { wait(); } 的编程范式,以避免条件不一致问题。

image

synchronized参考了MESA管程模型,对MESA模型进行了精简。在MESA 模型中,一个管程可以有多个条件变量,而Java中的synchronized机制只对应一个条件变量。

public class Test {public static void main(String[] args) {// 同步代码块方式加锁synchronized (Test.class) {}// 同步方法方式加锁func();}public static synchronized void func() {}
}

先使用javac编译,生成Test.class的文件。使用javap -c命令来查看字节码。

public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=3, args_size=10: ldc           #2                  // class com/tencent/trpcprotocol/dayu/identify/Test2: dup4: monitorenter6: monitorexit12: monitorexit15: invokestatic  #3                  // Method func:()V18: returnpublic static synchronized void func();descriptor: ()Vflags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZEDCode:stack=0, locals=0, args_size=00: returnLineNumberTable:line 25: 0

从字节码可以看出,同步代码块通过monitorenter和monitorexit指令实现锁的获取与释放,而同步方法通过ACC_SYNCHRONIZED标记隐式管理锁。无论采用哪种方式,其本质是对一个对象(Object)的监视器锁(Monitor locking)进行获取,它与synchronized 所在的对象一一对应。
当一个线程进入一个synchronized方法或代码块时,它会尝试获取该对象的监视器锁。如果锁没有被其他线程占用,该线程会获取到锁,并执行临界区的代码。如果锁已经被其他线程占用,该线程会进入阻塞(BLOCKED)状态,并进入同步队列等待锁的释放。
Java 中的 Object 类提供了wait()、notify() 和 notifyAll()方法,这些方法正是基于MESA 模型中的条件变量实现的。当线程执行wait()方法时,会释放锁,并将线程从运行状态转移到等待队列中;当线程被notify或notifyAll 唤醒后,会重新进入同步队列,参与锁的竞争,竞争成功后才能继续执行。
image

synchronized性能优化
synchronized在早期仅支持‌重量级锁‌(Mutex locking),依赖操作系统内核态与用户态的切换,性能较差。JDK 6后引入多级锁优化。
1)偏向锁(Biased Locking):针对同一线程反复获取同一锁的场景,偏向锁会记录首次获取锁的线程ID。后续该线程再次获取锁时,无需同步操作即可直接执行,从而消除不必要的锁竞争开销。
2)轻量级锁(Lightweight Locking):通过‌CAS操作和锁标记位实现。线程尝试以CAS方式将锁标记为轻量级状态,若成功则直接获取锁;若失败,则通过自旋等待锁释放。此机制在竞争不激烈时避免了内核态切换,显著提升锁操作效率。
3)自旋锁(Spin Locking):当锁获取失败时,线程会在有限次数内循环等待(自旋),而非立即进入阻塞状态。适用于锁持有时间极短的场景,通过减少线程挂起与唤醒开销提升性能。
4)锁消除(Lock Elimination):Java虚拟机的即时编译器在运行时分析代码,若检测到某些锁操作(如对局部对象的加锁)无实际意义,会自动移除这些锁,从而优化程序性能。

synchronized使用注意
1)避免死锁‌:如果两个或多个线程互相等待对方释放锁,会导致死锁。由于synchronized 不提供超时机制,可以使用 JUC并发包的ReentrantLock 并设置超时时间来避免死锁。

public class DeadlockAvoidance {private final Object lock1 = new Object();private final Object lock2 = new Object();// 线程1public void method1() {synchronized (lock1) {System.out.println(Thread.currentThread().getName() + " locked lock1");synchronized (lock2) {System.out.println(Thread.currentThread().getName() + " locked lock2");}}}// 线程2public void method2() {synchronized (lock1) {System.out.println(Thread.currentThread().getName() + " locked lock1");synchronized (lock2) {System.out.println(Thread.currentThread().getName() + " locked lock2");}}}
}

‌2)锁粒度:锁粒度指的是对共享资源加锁的范围。锁的粒度过大,会导致并发性能下降;锁的粒度过小,会增加锁管理的开销。

public class SynchronizedBlockExample {private int count = 0;// 只同步增量操作部分,避免同步无关代码public void increment() {synchronized (this) {count++;}}public int getCount() {return count;}
}

3)理解可重入性:synchronized 是可重入的,也就是说,同一个线程可以多次获得同一个锁而不会发生死锁

public class ReentrantLockExample {// 如果一个线程在同步方法内部调用了另一个同步方法,它仍然能获取锁public synchronized void methodA() {System.out.println("Entering method A");methodB();  // 调用另一个同步方法}public synchronized void methodB() {System.out.println("Entering method B");}
}

未完待续

很高兴与你相遇!如果你喜欢本文内容,记得关注哦

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

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

相关文章

网站建设项目进展情况汇报浙江省建设银行纪检官方网站

机器人模型获取 接上期:机器人控制系列教程之控制理论概述,文中详细讲解了如何通过Solidworks软件导出URDF格式的文件。文末提到了若需要将其导入到Simulink中可在命令行中输入smimport(urdf/S_Robot_urdf.urdf),MATLAB将自动打开Simulink以…

输入输出接口

IO接口的作用 又被称为IO控制器,设备控制器,负责协调主机和外部设备之间的数据传输 1.数据缓冲:通过数据缓冲寄存器(DBR)达到主机和外设的工作速度匹配 2.错误或状态检测:通过状态寄存器反馈设备的各种错误,状态…

Go语言中的信号捕获与优雅退出:SIGINT、SIGTERM和SIGKILL详解 - 若

在开发长期运行的服务时,如何让程序优雅退出是一个重要课题。今天我们来深入探讨Go语言中如何处理常见的进程信号,实现平滑关闭。 理解三个关键信号 1. SIGINT(信号2)- 礼貌的中断请求全称:Signal Interrupt触发方…

(二)3.1.9 生产“稳”担当:Apache DolphinScheduler Worker 服务源码全方位解析

本文是 Apache DolphinScheduler 3.1.9 版本源码解读的第二篇:Worker Server 启动流程源码解读以及相关流程设计。结尾处附有相关流程图,供大家参考。作者 | 李杰 移动云,Apache DolphinScheduler贡献者在现代数据驱…

实用指南:虚拟机搭建 DHCP 服务器 + 配置 DHCP 中继:完整实操指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

网站设计的技术方案wordpress安装主题教程

(来源:武汉市发改委)原标题:加快打造“五个中心” 武汉率先开建人工智能计算中心从华为东莞松山湖基地运来的预制化模块箱体,正在光谷科学岛起步区被吊装,未来将被“拼装”成武汉重要的人工智能算力基础设施。3月1日,武…

创建一个网站需要怎么做投票链接制作哪家服务好

在本篇文章里小编给大家整理的是一篇关于Python中免验证跳转到内容页的实例代码,有兴趣的朋友们可以学习分享下。相信很多人在浏览网页时,经常会碰到需要输入验证码才可以继续浏览的情况吧,遇到这种问题,大多数人只能进行繁琐的注…

海口建设局网站甘肃建设厅官方网站

Android 查看路由表_android 路由表_念雅的博客-CSDN博客

完整教程:生产环境实战:Spring Cloud Sleuth与Zipkin分布式链路追踪实践

完整教程:生产环境实战:Spring Cloud Sleuth与Zipkin分布式链路追踪实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family…

ibero 2025.1 Run PROGRAM_SPI_IMAGE_Action

ibero 2025.1 Run PROGRAM_SPI_IMAGE_Actionibero 2025.1 Run PROGRAM_SPI_IMAGE_ActionSPI Flash lemory is not configured. Use the Configure Design Initialization Data and memories tool to configure it按照以…

训练“系统级思维”,听时序数据库 IoTDB Committer 说说从设计到应用的成长

充满活力与机遇的开源社区,让我们完成从功能设计到系统应用的能力跃迁!想得更长远,离应用更近 2025 年 7 月 7 日、7 月 29 日,经 Apache IoTDB 社区投票,丁宇辰、曹志佳成为时序数据库 Apache IoTDB Committer。…

【设计模式】状态模式 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Kendo UI for jQuery 2025 Q3新版亮点 - AI 智能网格与全新表单体验

Kendo UI for jQuery 2025 Q3新版亮点 - AI 智能网格与全新表单体验Telerik和Kendo UI的 2025 Q3 版本(发布于 2025 年 8 月)为开发者带来了全面升级:AI 编码助手首次在所有主要 UI 库(包括 Angular、Blazor、.NET…

网站自助建站软件可以免费做中考题的网站

进入题目页面如下 提示flag在flag.php ctrlu&#xff0c;查看源码 给出了一段PHP代码&#xff0c;进行代码审计 <?php // 检查是否开启了错误显示功能 if( !ini_get(display_errors) ) {// 如果没有开启&#xff0c;则将错误显示功能设置为开启状态ini_set(display_error…

关于gradle项目启动

关于gradle项目启动首先idea上要开启gradle,即在构建工具项中要能看到gradle,如果没有去插件中开启,可能关了。 关于加速:项目根目录下的settings.gradlepluginManagement {println "aliyun pluginManagement…

网站建设用什么网站后台编辑器无法显示

基本介绍 函数指针:指向函数的指针 与数组类似 定义 Int(*pmax)(int ,int)max; Int(*pmax)(int x,int y)max;//形参名称不重要 函数返回类型(*指针)(形参类型)函数名称; 具体案例 代码: *pmax取到函数本身 调用函数指针方式: (*pmax)(x,y); pmax(x,y);//与java中调用函数一…

青海省交通建设厅网站网站建设加关键词是什么意思

文章目录 1. 字体设置推荐2. 主题推荐3. Rainbow Brackets(彩虹括号)4. 设置背景图片 下面是我的 IDEA 主题和字体&#xff0c;它们的搭配效果如下&#xff1a; 1. 字体设置推荐 在使用 IntelliJ IDEA 进行编码和开发时&#xff0c;一个合适的字体设置可以提高你的工作效率和舒…

事倍功半是蠢蛋55 ctrl+shift+f 每次搜索都按倒繁体

如果您使用的是「微软拼音输入法」 打开 设置 > 时间和语言 > 语言和区域。 在首选语言下,点击 中文(简体,中国) 旁边的“...”按钮,选择 语言选项。 找到 微软拼音,点击其旁边的“...”按钮,选择 键盘选…

PHP 线上环境 Composer 依赖包更新部署指南-简易版 - 教程

PHP 线上环境 Composer 依赖包更新部署指南-简易版 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consola…

完整教程:Ubuntu 安装和配置 Anaconda

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …