synchronized关键字以及底层实现

目录

基本使用

底层实现

synchronized锁升级

对象的内存结构

ⅰ. 对象头

1. ① 运行时元数据 (Mark Word) (占64位)

a. 哈希值 (HashCode)

b. GC分代年龄

c. 锁状态标记

2. ② 类型指针: (Klass Point) (占 32位)

ⅱ. 实例数据

ⅲ. 对齐填充

Moniter重量级锁

轻量级锁

偏向锁


基本使用

Java中的synchronized关键字主要用于实现线程同步,确保在多线程环境下同一时间只有一个线程可以访问被它保护的代码块或方法。以下是synchronized的基本使用方式:

1.修饰非静态方法

public class MyClass {private int count;// 一个同步实例方法public synchronized void increment() {count++;}
}

 在这个例子中,synchronized关键字修饰了increment()方法。这意味着任何时刻只有一个线程可以执行该方法,其他试图同时访问此方法的线程将会阻塞,直到当前线程完成方法调用并释放锁。

 2.修饰静态方法

public class MyClass {private static int staticCount;// 一个同步静态方法public static synchronized void incrementStatic() {staticCount++;}
}

synchronized修饰静态方法时,它锁定的是类对象(即Class级别的锁),因此,在多线程环境中,所有对该类静态方法的访问将被串行化。 

 3.修饰代码块

public class MyClass {private final Object lock = new Object();private int instanceCount;public void incrementInstanceCount() {// 同步代码块synchronized (lock) {instanceCount++;}}
}

这里synchronized用于一个代码块,它可以根据需要指定一个特定的对象作为锁对象(这里是lock对象)。只有获取到这个对象锁的线程才能进入并执行同步代码块内的内容。

底层实现

 javap -v xx.class   查看class字节码信息

synchronized关键字在Java中的底层原理主要涉及操作系统层面的互斥锁(Monitor)机制,以及JVM内部的实现细节

JVM使用monitorenter和monitorexit指令来实现对监视器的操作。

  • 当执行到monitorenter指令时,如果对象没有被锁定或者当前线程已经持有该对象的锁,则将锁计数器加1,并允许线程继续执行同步代码块。
  • 当执行到monitorexit指令时,锁计数器减1;当计数器为0时,表示锁被释放,其他等待该锁的线程可以有机会竞争获取锁并执行相应代码。

Monitor 被翻译为监视器,是由jvm提供,c++语言实现

Owner:存储当前获取锁的线程的,只能有一个线程可以获取

EntryList:关联没有抢到锁的线程,处于Blocked状态的线程

WaitSet:关联调用了wait方法的线程,处于Waiting状态的线程

synchronized锁升级

Monitor实现的锁属于重量级锁,里面涉及到了用户态和内核态的切换、进程的上下文切换,成本较高,性能比较低。

synchronized锁升级是Java 1.6及以后版本引入的一种优化机制,目的是为了在多线程环境下更好地平衡锁的性能和资源消耗。在早期版本中,Java对于synchronized关键字的实现是直接使用重量级锁(即操作系统互斥量Mutex),这种方式虽然能够确保线程安全,但其开销较大,尤其是在锁竞争不激烈的情况下。

在HotSpot虚拟机中,对象在内存中存储的布局可分为3块区域:对象头(Header)、实例数据(Instance Data)和对齐填充

对象的内存结构

ⅰ. 对象头

1. ① 运行时元数据 (Mark Word) (占64位)
a. 哈希值 (HashCode)

31位的对象标识,采用延迟加载技术,调用 System.identityHashCode() 计算得到,并将结果写到对象头中,用于栈空间中,对对象的引用的指向,不然是无法找到堆中的对象的

b. GC分代年龄

(占用4位) 记录着幸存者区对象被GC过后的age, 一般age为15, 如果对象的gc次数到达了这个值,将进入老年代

c. 锁状态标记

记录加锁的一些信息

  1. hashcode:25位的对象标识Hash码
  2. age:对象分代年龄占4位
  3. biased_lock:偏向锁标识,占1位 ,0表示没有开始偏向锁,1表示开启了偏向锁
  4. thread:持有偏向锁的线程ID,占23位
  5. epoch:偏向时间戳,占2位
  6. ptr_to_lock_record:轻量级锁状态下,指向栈中锁记录的指针,占30位
  7. ptr_to_heavyweight_monitor:重量级锁状态下,指向对象监视器Monitor的指针,占30位
2. ② 类型指针: (Klass Point) (占 32位)

是对方法区中,类的元信息的引用

ⅱ. 实例数据

真实的记录一个对象包含的数据,比如Cat类对象 ,里面包含 name,age 等等相关的信息,如果有字符串,要引用字符串常量池

ⅲ. 对齐填充

仅起到占位符的作用 ,因为 HotSpot虚拟机要求对象的起始地址必须是8字节的整数,如果达不到,用对齐添充的方式补齐,为什么是8呢,因为64位的机器能被8整除,效率高

Moniter重量级锁

每个 Java 对象都可以关联一个 Monitor 对象,如果使用 synchronized 给对象上锁(重量级)之后,该对象头的Mark Word 中就被设置指向 Monitor 对象的指针

轻量级锁

在很多的情况下,在Java程序运行时,同步块中的代码都是不存在竞争的,不同的线程交替的执行同步块中的代码。这种情况下,用重量级锁是没必要的。因此JVM引入了轻量级锁的概念。

加锁流程

1.在线程栈中创建一个Lock Record,将其obj字段指向锁对象。
2.通过CAS指令将Lock Record的地址存储在对象头的mark word中,如果对象处于无锁状态则修改成功,代表该线程获得了轻量级锁。
3.如果是当前线程已经持有该锁了,代表这是一次锁重入。设置Lock Record第一部分为null,起到了一个重入计数器的作用。
4.如果CAS修改失败,说明发生了竞争,需要膨胀为重量级锁。

解锁过程

1.遍历线程栈,找到所有obj字段等于当前锁对象的Lock Record。
2.如果Lock Record的Mark Word为null,代表这是一次重入,将obj设置为null后continue。
3.如果Lock Record的 Mark Word不为null,则利用CAS指令将对象头的mark word恢复成为无锁状态。如果失败则膨胀为重量级锁。

偏向锁

轻量级锁在没有竞争时(就自己这个线程),每次重入仍然需要执行 CAS 操作。 Java 6 中引入了偏向锁来做进一步优化:只有第一次使用 CAS 将线程 ID 设置到对象的 Mark Word 头,之后发现 这个线程 ID 是自己的就表示没有竞争,不用重新 CAS。以后只要不发生竞争,这个对象就归该线程所有

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

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

相关文章

[ai笔记3] ai春晚观后感-谈谈ai与艺术

欢迎来到文思源想的ai空间,这是技术老兵重学ai以及成长思考的第3篇分享! 今天我们不聊技术,只聊感受! 1 关于ai春晚 期待许久的ai春晚,但是等初一晚上观看的时候,或多或少还是有些失望。 首先是观看人数…

前端工程化面试题 | 06.精选前端工程化高频面试题

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

【二叉树】构建销毁二叉树

目录 创建二叉树 整体思路 代码实现 图示理解​ 销毁二叉树 判断二叉树是否是完全二叉树&层序 整体思路 代码实现 图是理解 二叉树的性质 题目 创建二叉树 整体思路 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树遇到#就回退,返回…

浅谈路由器交换结构

一、路由器技术概述 路由器(Router)是连接两个或多个网络的硬件设备,在网络间起网关的作用,是读取每一个数据包中的地址然后决定如何传送的专用智能性的网络设备。它能够理解不同的协议,例如某个局域网使用的以太网协议…

文章页的上下篇功能是否有必要?boke112百科取消上下篇功能

也不知道是从什么时候开始,我们很多站长的博客网站文章页都会在文末添加上“上一篇”和“下一篇”功能,目的是进行站内SEO优化和方便用户阅读上下篇文章。 boke112百科不管是以前使用的Three主题还是现在使用的YIA主题,刚开始的文章页都是有…

学习Android的第十天

目录 Android CheckBox 复选框 获得选中的 CheckBox 的值 自定义点击效果 改变文字与选择框的相对位置 修改文字与选择框的距离 Android ToggleButton 开关按钮 改变 ToggleButton 的状态和文本 Android Switch 开关 改变 Switch 的状态和文本 Android CheckBox 复选框…

腾讯云4核8G服务器可以用来干嘛?怎么收费?

腾讯云4核8G服务器适合做什么?搭建网站博客、企业官网、小程序、小游戏后端服务器、电商应用、云盘和图床等均可以,腾讯云4核8G服务器可以选择轻量应用服务器4核8G12M或云服务器CVM,轻量服务器和标准型CVM服务器性能是差不多的,轻…

sheng的学习笔记-docker部署springboot

部署文章目录:目录 docker部署,原理,命令,可以参考:docker原理图,部署,命令 目录 将springboot部署到docker中 遇到过的问题: pom配置 操作步骤 生成jar 构建镜像 查看镜像d…

CTFshow-WEB入门-信息搜集

web1(查看注释1) wp 右键查看源代码即可找到flag web2(查看注释2) wp 【CtrlU】快捷键查看源代码即可找到flag web3(抓包与重发包) wp 抓包后重新发包,在响应包中找到flag web4(robo…

物联网和工业4.0

在当今这个快速发展的技术时代,物联网(IoT)和工业4.0成为了推动全球进入新工业时代的两大驱动力。对于刚入行的人来说,深入理解这两个概念及其背后的技术原理,对于把握未来的职业机会至关重要。 物联网,简…

关于java的多线程初识

关于java的多线程初识 我们从今天开始,正式学习java的多线程,我们在前面的文章中学习到了java的基础, 但是距离我们工作实战还差的很远,我们学习好了基础,以后的文章会逐步的深入,去讲解各种前端框架&…

Flink从入门到实践(三):数据实时采集 - Flink MySQL CDC

文章目录 系列文章索引一、概述1、版本匹配2、导包 二、编码实现1、基本使用2、更多配置3、自定义序列化器4、Flink SQL方式 三、踩坑1、The MySQL server has a timezone offset (0 seconds ahead of UTC) which does not match the configured timezone Asia/Shanghai. 参考资…

【python】网络爬虫与信息提取--requests库

导学 当一个软件想获得数据,那么我们只有把网站当成api就可以 requests库:自动爬取HTML页面,自动网络请求提交 robots协议:网络爬虫排除标准(网络爬虫的规则) beautiful soup库:解析HTML页面 工具&…

算法---回溯(正文)

1.什么是回溯? 回溯算法的定义就是和暴力枚举一样枚举所有可能并加撤回,也能和暴力一样去掉一些重复(在之前就被筛出,但还要枚举这个,我们可以跳过这个了---------这个就是回溯剪枝)。但为什么回溯不是暴力…

【精选】java多态进阶——多态练习测试

🍬 博主介绍👨‍🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~ ✨主攻领域:【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 🎉点赞➕评论➕收藏…

Mac上新版InfluxDB使用教程

一、简介 官网:influxdb 二、influxdb安装 建议使用Homebrew在 macOS 上安装 InfluxDB v2: brew install influxdb启动influxdb服务:brew services start influxdb 停止influxdb服务:brew services stop influxdb 查看是否启…

使用R语言fifer包进行分层采样

使用R语言fifer包中的stratified()函数用来进行分层采样非常方便,但fifer包已经从CRAN存储库中删除,需要从存档中下载可用的历史版本,下载链接:Index of /src/contrib/Archive/fifer (r-project.org)https://cran.r-project.org/s…

opencv 图像色彩空间转化

今天看了b站贾志刚的课,觉得不错,特地做学习笔记来和小伙伴分享 贾志刚的这个好像是2.0版本,30小时的,语言更加精炼,适合初级入门学习 第一节是常规安装 看他的步骤装就行了,记得配置完点应用再点确定,我第一次就是 没点然后就失败了,又得重配置一次…

python+flask+django农产品供销展销电子商务系统lkw43

供销社农产品展销系统的设计与实现,最主要的是满足使用者的使用需求,并且可以向使用者提供一些与系统配套的服务。本篇论文主要从实际出发,采用以对象为设计重点的设计方法,因此在进行系统总体的需求分时借助用例图可以更好的阐述…

电缆线的阻抗50Ω,真正含义是什么?

当我们提到电缆线的阻抗时,它到底是什么意思?RG58电缆通常指的是50Ω的电缆线。它的真正含义是什么?假如取一段3英尺(0.9144米)长的RG58电缆线,并且在前端测量信号路径与返回路径之间的阻抗。那么测得的阻抗是多少?当然…