详细聊聊 Synchronized,以及锁的升级过程

在Java中,synchronized关键字是用于实现线程同步的重要机制,它通过内置锁(Monitor)确保多个线程对共享资源的安全访问。


1. synchronized 的基本使用与实现原理

使用方式
  • 修饰实例方法:锁是当前对象实例。
    public synchronized void method() { ... }
    
  • 修饰静态方法:锁是当前类的Class对象。
    public static synchronized void staticMethod() { ... }
    
  • 同步代码块:需显式指定锁对象(任意对象均可)。
    synchronized (lockObject) { ... }
    
底层实现
  • Monitor 机制:每个对象关联一个Monitor(监视器锁),通过monitorentermonitorexit字节码指令实现加锁/解锁。
    • 线程进入同步块时,执行monitorenter尝试获取锁。
    • 退出同步块时,执行monitorexit释放锁。

2. 对象头与锁状态标记

每个Java对象在内存中分为三部分:对象头(Header)实例数据(Instance Data)对齐填充(Padding)。对象头中的Mark Word字段记录了锁状态信息。

Mark Word 结构(以64位JVM为例)
锁状态存储内容
无锁对象的哈希码、分代年龄、是否偏向锁(1 bit)
偏向锁偏向线程ID、偏向时间戳、分代年龄、锁标志位(01)
轻量级锁指向线程栈中锁记录(Lock Record)的指针,锁标志位(00)
重量级锁指向Monitor对象(重量级锁)的指针,锁标志位(10)

3. 锁的升级过程

JVM根据线程竞争情况动态调整锁状态,以减少性能开销。锁升级的路径为:
无锁 → 偏向锁 → 轻量级锁 → 重量级锁

(1) 偏向锁(Biased Locking)
  • 适用场景:单线程反复进入同步块,无实际竞争。
  • 核心机制
    • 对象首次被线程访问时,将线程ID写入Mark Word,进入偏向模式。
    • 后续该线程进入同步块时,无需执行CAS操作,直接检查线程ID是否匹配。
  • 优势:消除无竞争时的同步开销。
  • 撤销条件
    • 其他线程尝试获取锁时,触发偏向锁撤销。
    • 需要等待全局安全点(STW),检查原线程是否存活或已释放锁。
(2) 轻量级锁(Lightweight Locking)
  • 适用场景:多线程交替执行同步块,竞争不激烈。
  • 核心机制
    • 线程在栈帧中创建锁记录(Lock Record),将对象Mark Word复制到锁记录中。
    • 通过CAS将Mark Word替换为指向锁记录的指针。成功则获取锁;失败则膨胀为重量级锁。
  • 优势:避免线程阻塞,通过自旋(CAS)减少内核态切换开销。
  • 自旋优化
    • 适应性自旋:JVM根据历史自旋成功率动态调整自旋次数。
(3) 重量级锁(Heavyweight Locking)
  • 适用场景:多线程高并发竞争。
  • 核心机制
    • Monitor对象(C++实现)管理线程竞争,包含_owner(持有者)、_EntryList(阻塞队列)、_WaitSet(等待队列)。
    • 未获取锁的线程进入_EntryList,由操作系统调度(涉及用户态到内核态切换)。
  • 特点:线程阻塞,响应慢但公平。

4. 锁升级的触发条件

步骤触发条件
无锁 → 偏向锁对象首次被线程访问,JVM启用偏向锁(默认开启,Java 15后需手动开启)。
偏向锁 → 轻量级锁其他线程尝试获取锁,导致偏向锁撤销。
轻量级锁 → 重量级锁CAS自旋失败(超过阈值或竞争激烈),触发锁膨胀(Inflate)。

5. 锁的不可逆性与性能权衡

  • 不可逆性:锁升级后无法降级,因为降级会增加复杂性和性能损耗。
  • 性能权衡
    • 偏向锁:适合单线程场景,但撤销成本高(需STW)。
    • 轻量级锁:适合低竞争场景,依赖CAS自旋。
    • 重量级锁:适合高竞争场景,牺牲响应时间保证稳定性。

6. Monitor 的详细结构

Monitor对象(如ObjectMonitor)包含以下关键字段:

  • _owner:当前持有锁的线程。
  • _recursions:锁的重入次数。
  • _EntryList:等待获取锁的线程队列。
  • _WaitSet:调用wait()后进入等待状态的线程队列。

7. 实际案例:锁升级过程

场景:两个线程交替执行同步块
  1. 初始状态:对象无锁。
  2. 线程A进入同步块:升级为偏向锁,Mark Word记录线程A的ID。
  3. 线程B尝试进入:触发偏向锁撤销,升级为轻量级锁,线程B通过CAS竞争。
  4. 线程B CAS失败:自旋后仍未成功,升级为重量级锁,线程B进入_EntryList阻塞。

8. 最佳实践

  • 避免过度同步:减少锁粒度(如使用ConcurrentHashMap)。
  • 优先使用轻量级工具:如ReentrantLockStampedLock(需手动管理)。
  • 监控锁竞争:通过JVM参数(-XX:+PrintFlagsFinal)或工具(Arthas)分析锁状态。

在这里插入图片描述

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

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

相关文章

vue3的深入组件-组件 v-model

组件 v-model 基本用法​ v-model 可以在组件上使用以实现双向绑定。 从 Vue 3.4 开始&#xff0c;推荐的实现方式是使用 defineModel() 宏&#xff1a; <script setup> const model defineModel()function update() {model.value } </script><template>…

15.thinkphp的上传功能

一&#xff0e;上传功能 1. 如果要实现上传功能&#xff0c;首先需要建立一个上传表单&#xff0c;具体如下&#xff1a; <form action"http://localhost/tp6/public/upload"enctype"multipart/form-data" method"post"><input type&…

word文档基本操作: 编辑页眉页脚和插入目录

文章目录 引言I 编辑页眉页脚II 插入目录III 知识扩展基于axure画架构图基于Knife4j导出接口文档基于PDManer导出数据库设计文档引言 背景: 信息安全认证需要准备相关文件用于审核 一般的开发设计包含总体设计、概要设计、详细设计、接口设计、数据库设计、部署结构设计、原型…

Qt 通过控件按钮实现hello world + 命名规范(7)

文章目录 使用编辑框来完成 hello world通过编辑图形化界面方式通过纯代码方式 通过按钮的方式来创建 hello world通过编辑图形化界面方式通过纯代码方式 总结Qt Creator中的快捷键如何使用文档命名规范 简介&#xff1a;这篇文章着重点并不在于创建hello world程序&#xff0c…

实时网络流量监控与防御:Python实现DDoS攻击检测

1. 需求分析 DDoS攻击通过海量请求耗尽服务器资源。本文使用 Python Scapy 实时监控流量&#xff0c;自动触发IP封禁。 2. 核心代码实现 2.1 依赖安装 pip install scapy psutil2.2 流量监控脚本&#xff08;ddos_detector.py&#xff09; import time from scapy.all im…

电赛经验分享——模块篇

1、前言 打算在这一个专栏中&#xff0c;分享一些本科控制题电赛期间的经验&#xff0c;和大家共同探讨&#xff0c;也希望能帮助刚刚参加电赛的同学&#xff0c;了解一些基本的知识。一些见解和看法可能不同或有错误&#xff0c;欢迎批评指正。 在本文中&#xff0c;主要介绍笔…

【LLM】Open WebUI 使用指南:详细图文教程

Open WebUI 是一个开源的、可扩展且用户友好的自托管 AI 平台,专为生成式人工智能模型交互而设计。 Open WebUI 旨在为用户提供一个简单易用、功能强大且高度定制化的界面,使其能够轻松与各种 AI 模型(如文本生成、图像生成、语音识别等)进行交互。 一、安装与初始化配置 扩…

HarmonyOS Next~HarmonyOS应用测试全流程解析:从一级类目上架到二级类目专项测试

HarmonyOS Next&#xff5e;HarmonyOS应用测试全流程解析&#xff1a;从一级类目上架到二级类目专项测试 引言&#xff1a;HarmonyOS生态下的质量保障挑战 在万物互联的智能时代&#xff0c;HarmonyOS作为分布式操作系统&#xff0c;为开发者带来了前所未有的创新空间&#x…

一种机载扫描雷达实时超分辨成像方法——论文阅读

一种机载扫描雷达实时超分辨成像方法 1. 专利的研究目标与产业意义1.1 研究目标与实际问题1.2 产业意义2. 专利的创新方法:滑窗递归优化与实时更新2.1 核心模型与公式2.2 与传统方法对比优势3. 实验设计与验证3.1 仿真参数3.2 实验结果4. 未来研究方向与挑战4.1 学术挑战4.2 技…

滚筒洗衣机拆解学习

本文图片来自于B站视频&#xff0c;链接在文末&#xff0c;不涉及任何公司及实验室产品 对小米滚筒洗衣机进行拆解&#xff0c;并收集了用户对这款产品的评价&#xff0c;认识了关键部件。下一步重点学习对各个电机的控制逻辑和供电系统。 整机拆解学习&#xff1a; 功能面板…

【金仓数据库征文】金仓数据库 KingbaseES 在电商平台数据库迁移与运维中深入复现剖析

【金仓数据库征文】金仓数据库 KingbaseES 在电商平台数据库迁移与运维中深入复现剖析 前言 在当今数字化商业蓬勃发展的时代&#xff0c;电商平台的数据量呈爆发式增长&#xff0c;对数据库性能、稳定性和扩展性提出了极高要求。本文章基于大型电商平台原本采用 MySQL 数据库&…

iPhone手机连接WiFi异常解决方法

iPhone手机连接WiFi异常解决方法 一、问题现象二、iPhone连不上可能的原因三、基础排查与快速修复第一步:重启大法第二步:忽略网络,重新认证第三步:关闭“私有无线局域网地址”第四步:修改DNS服务器第五步:还原网络设置四、路由器端排查及设置关闭MAC地址过滤或添加到白名…

Android NDK版本迭代与FFmpeg交叉编译完全指南

在Android开发中&#xff0c;使用NDK(Native Development Kit)进行原生代码开发是一项常见需求&#xff0c;特别是当我们需要集成FFmpeg这样的多媒体处理库时。本文将深入分析Android NDK的版本迭代分界线&#xff0c;详细讲解FFmpeg交叉编译的注意事项&#xff0c;并提供完整的…

typecho中的Widget设计文档

组成系统的最基本元素 什么是Widget Widget是组成Typecho的最基本元素&#xff0c;除了已经抽象出来的类库外&#xff0c;其它几乎所有的功能都会通过Widget来完成。在实践中我们发现&#xff0c;在博客这种小型但很灵活的系统中实施一些大型框架的思想是不合适的&#xff0c…

Python序列Day3

序列 序列是一种数据存储方式&#xff0c;用方括号标注&#xff0c;逗号分隔的一组值。在内存中&#xff0c;序列就是一块用来存放多个值的连续的内存空间。 常见序列结构有&#xff1a;字符串、列表、元组、字典、集合 列表 用于存储任意数目&#xff0c;任意类型的数据集…

私服与外挂:刑事法律风险的深度剖析

首席数据官高鹏律师团队编著 在当今数字化时代&#xff0c;网络游戏产业蓬勃发展&#xff0c;然而与之相伴的私服与外挂现象却屡禁不止&#xff0c;且其背后隐藏着严重的刑事法律风险。作为一名律师&#xff0c;有必要在此对私服与外挂相关的刑事问题进行深入解读&#xff0c;以…

Linux云计算训练营笔记day04(Rocky Linux中的命令)

mv 移动(剪切) 源数据会消失 格式: mv 源文件 目标路径 touch /opt/a.txt 创建文件 mv /opt/a.txt /root 移动文件&#xff0c;没有改名 mkdir gongli 创建目录 mv gongli /opt/ 移动目录&#xff0c;没有改名 mv /opt/gongli tedu 移动目录&#xff0c;改名了 …

蓝桥杯青少 图形化编程——“星星”点灯

蓝桥杯青少 图形化编程——“星星”点灯 编程实现&#xff1a; 有10盏灯&#xff0c;从1到10按顺序依次编号&#xff0c;初始时全部灯处于开启状态。有10个人也从1到10依次编号。第一个人&#xff08;1号&#xff09;将灯全部关闭&#xff0c;第二个人&#xff08;2号&#x…

conda配置好的pytorch在jupyter中如何配置

配置 其实不用再配置了 如下图&#xff08;主要是激活pytorch环境&#xff0c;再jupyter notebook&#xff09; jupyter运行快捷键shiftenter 新建文件夹folder&#xff0c;新建notebook 使用 帮助文档&#xff08;两种方式&#xff09; ctrl/ 注释

COLT_CMDB_aix_diskinfo.sh

#!/bin/ksh #IT_BEGIN #IT_TYPE3 #IT SYSTEM_AIX_AGENTDISKDISCOVER|discovery.diskInfo[disc] #原型指标 #IT_RULE SYSTEM_AIX_IP|ipAddress[{#DISKNAME}] #IT_RULE SYSTEM_AIX_AGENTDISKPATH|diskPath[{#DISKNAME}] #IT_RULE SYSTEM_AIX_DISKNAME|diskName[{#DISKNAME}] #IT_…