【JUC进阶】08. 重量级锁

news2024/11/24 17:31:58

目录

1、前言

2、重量级锁

3、数据结构和控制流程

3.1、Monitor 对象

3.2、控制流程

4、性能分析

5、同其他锁的对比


1、前言

前面我们介绍了偏向锁,轻量级锁,自旋锁相关知识。初次之外,锁升级过程还会涉及到重量级锁。重量级锁是并发编程中常用的同步机制之一,它能够确保对共享资源的互斥访问,但由于其较高的开销,需要在合适的场景中使用。今天我们就来深入聊聊关于重量级锁,以及他的原理和性能分析。

2、重量级锁

在 JVM 中,重量级锁的实现主要依赖于操作系统提供的底层互斥锁机制。JVM 使用了操作系统的互斥原语(Mutex)来实现重量级锁的功能。

其实现原理:

  1. 对象头中的 Mark Word:每个 Java 对象在内存中都有一个对象头,其中的 Mark Word 被用于存储对象的锁状态信息。在重量级锁的情况下,Mark Word 中会记录指向重量级锁(即互斥锁)的指针。
  2. Monitor(监视器):重量级锁的核心是 Monitor 对象,它用于控制对共享资源的访问。每个 Java 对象都有一个与之关联的 Monitor 对象,用于管理对象的锁状态。
  3. 线程的阻塞和唤醒:当一个线程尝试获取一个被其他线程持有的重量级锁时,它会进入阻塞状态。在 JVM 中,线程的阻塞和唤醒是通过操作系统提供的底层原语实现的。具体来说,当线程无法获取锁时,JVM 会调用操作系统提供的阻塞原语将线程置于等待状态,并将其从运行队列中移除。当锁被释放时,JVM 会通过操作系统提供的唤醒原语将等待的线程重新加入到运行队列中。
  4. 操作系统的互斥锁:JVM 通过操作系统提供的互斥锁机制来实现对重量级锁的互斥访问。具体来说,JVM 在内部使用操作系统提供的互斥原语(如互斥量、信号量等)来实现对 Monitor 对象的互斥访问。当一个线程获取锁时,JVM 会请求操作系统分配一个互斥锁,并将其锁定,从而保证同一时间只有一个线程可以访问被锁定的 Monitor 对象。

3、数据结构和控制流程

重量级锁的数据结构和控制流程主要涉及 Monitor 对象和线程的阻塞与唤醒。

3.1、Monitor 对象

Monitor 对象是重量级锁的核心数据结构,用于控制对共享资源的访问。每个 Java 对象都会关联一个 Monitor 对象,用于管理对象的锁状态。

Monitor 对象包含了以下信息:

  1. Owner:记录当前持有锁的线程。
  2. Entry Set:记录等待获取锁的线程队列,采用先进先出的顺序。
  3. Wait Set:记录因调用了 wait() 方法而进入等待状态的线程队列,也是先进先出的顺序。
  4. 计数器:用于记录当前持有锁的线程重入的次数。

3.2、控制流程

  1. 线程尝试获取锁:
    1. 当一个线程尝试获取一个被其他线程持有的重量级锁时,它会进入阻塞状态。
    2. 线程通过检查 Monitor 对象的状态来判断是否可以获取锁。
    3. 如果锁处于可用状态,线程会成功获取锁,并将 Monitor 对象的 Owner 字段指向当前线程。
    4. 如果锁已被其他线程持有,当前线程会被放入 Monitor 对象的 Entry Set 中等待。
  2. 线程释放锁:
    1. 当线程释放锁时,它会将 Monitor 对象的 Owner 字段置为 null,表示锁已被释放。
    2. 如果 Monitor 对象的 Entry Set 非空,则会从队列头部取出一个线程唤醒,使其尝试获取锁。
  3. 线程进入等待状态:
    1. 当线程调用 wait() 方法时,它会释放持有的锁,并将线程置于 Monitor 对象的 Wait Set 中等待。
    2. 线程会等待其他线程调用相同 Monitor 对象的 notify() 或 notifyAll() 方法来唤醒它。

4、性能分析

重量级锁在性能方面存在一些局限性。

  1. 线程阻塞与唤醒开销:当一个线程尝试获取重量级锁时,如果锁已经被其他线程持有,该线程会进入阻塞状态,并被放入等待队列中。当锁被释放时,需要唤醒等待队列中的线程。这涉及到线程的上下文切换、状态转换以及线程间的通信,会带来较大的开销。
  2. 线程调度开销:重量级锁依赖于操作系统对线程的调度机制。当一个线程被阻塞时,操作系统需要重新调度其他可执行线程,这涉及到上下文切换和线程调度算法,会引入较高的开销。
  3. 竞争激烈时的争用:重量级锁在高并发环境下,由于需要线程的阻塞与唤醒操作,会引发较大的竞争,导致锁的争用激烈。这可能会导致大量的线程等待锁的释放,降低系统的并发性能。

可以采用一些优化策略:

  1. 减少锁的持有时间:尽量缩小锁的范围,减少锁的持有时间,以降低线程等待锁的时间。
  2. 使用细粒度锁:如果可能,将大锁拆分为多个小锁,以减少锁的争用范围。
  3. 无锁算法和乐观锁:对于一些适合无锁或乐观锁的场景,可以考虑使用无锁算法或乐观锁来避免使用重量级锁。
  4. 使用其他同步机制:根据具体场景,可以选择适当的同步机制,如读写锁、信号量、并发集合等,来替代重量级锁。

5、同其他锁的对比

其实不难发现,前面几种锁的介绍,到现在重量级锁,这些都是为了保证数据并发安全,而做的一系列锁优化升级,随着竞争情况逐步升级,相应的对于性能的开销也是越来越大。

  1. 偏向锁:偏向锁是针对只有一个线程访问同步代码块的情况而设计的,它通过在对象头中的标记字段记录锁的信息,避免了多个线程之间的竞争。因此,偏向锁的性能开销非常低,适用于对同步频率较低的场景。
  2. 自旋锁:自旋锁是在多个线程之间进行忙等待,不会让线程阻塞,而是让线程不断自旋尝试获取锁,以避免线程切换的开销。自旋锁适用于锁竞争时间短、线程数较少的情况,可以有效减少线程上下文切换的开销。
  3. 轻量级锁:轻量级锁是一种在锁竞争激烈的情况下进行优化的锁机制。它通过使用CAS操作来避免线程阻塞和唤醒的开销,并使用对象头中的标志字段表示锁的状态。轻量级锁在多个线程之间进行自旋等待,如果自旋等待失败,则升级为重量级锁。轻量级锁适用于锁竞争不激烈的情况,可以减少线程切换的开销。
  4. 重量级锁:重量级锁是一种使用操作系统提供的互斥量实现的锁机制。它涉及到线程的阻塞和唤醒,需要操作系统的介入。重量级锁适用于锁竞争激烈、线程持有锁的时间较长的情况。

性能方面,偏向锁的性能最好,因为它几乎没有额外的开销。自旋锁和轻量级锁的性能较好,它们通过自旋等待来减少线程切换的开销。而重量级锁的性能较差,因为它涉及到线程阻塞和唤醒,需要操作系统的介入。

在JDK6之前,synchronized使用的便是重量级锁。而到了1.6之后,引入了无锁,偏向锁,轻量级锁以及自适应自旋锁等优化。这就有了之后的“无锁->偏向锁→轻量级锁→>重量级锁”的升级过程。

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

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

相关文章

基于Java珠宝首饰交易平台设计实现(源码+lw+部署文档+讲解等)

博主介绍:✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专…

新品预告——旗舰级DG4Pros最详技术解析及应用方案介绍

旗舰级DG4Pros RIY-DG4Pros是目前睿铂性能指标最高的一款全画幅倾斜摄影相机,其核心光学组件部分由睿铂结合多年来的用户反馈与对倾斜摄影技术的探索成果,完全自主研发设计,技术水平领先于市面同类产品。相机镜头内置双高斯结构和超低色散非…

Spring Boot 中的 Type-safe Configuration Properties:原理、用法与示例

Spring Boot 中的 Type-safe Configuration Properties:原理、用法与示例 前言 Spring Boot 是一个快速开发 Spring 应用程序的框架,它提供了很多有用的功能和特性。其中,Type-safe Configuration Properties 是一个常用的功能,…

基于STL的演讲比赛流程管理

比赛规则: 学校举行一场演讲比赛,共有12个人参加。比赛共两轮,第一轮为淘汰赛,第二轮为决赛。每名选手都有对应的编号,如10001~10012 比赛方式:分组比赛,每组6个人; 第一轮分为两个小组,整体按…

python: more Layer Architecture and its Implementation in Python and mysql 8.0

mysql 8.0 drop table DuStudentList;#学生表create table DuStudentList (StudentId INT NOT NULL AUTO_INCREMENT comment主键id, #自动增加,StudentName nvarchar(50) comment学生姓名,StudentNO varchar(50) comment学号, #学号StudentBirthday datet…

单片机学习12-串口通信

目录 串口通信实验 通信的基本概念 串行通信与并行通信 异步通信与同步通信 单工、半双工与全双工通信 通信速率(比特率) 单片机串口介绍 串口通信简介 串口相关寄存器 串口工作方式 方式 0 方式 1 方式 2 和方式 3 串口的使用方法 硬件设计…

基于matlab使用形态操作对视频流中的对象进行计数(附源码)

一、前言 此示例演示如何使用形态操作对视频流中的对象进行计数 输入视频流包含订书钉的图像。在此示例中,您使用平顶形态操作来消除不均匀的照明,并使用打开形态操作来消除订书钉之间的间隙。然后,将图像转换为二进制,对每个帧…

【Java】网络通信基础、协议分层及封装分用

IP地址:端口号概念格式 协议五元组协议分层TCP/IP五层模型 封装和分用 网络互连的目的是进行网络通信,也就是网络数据传输,更具体一点,是网络主机中的不同进程间基于网络来传输数据。 IP地址:端口号 概念 ip地址表示…

数据库监控与调优【十七】—— 表结构设计优化

表结构设计优化 第一范式(1NF) 字段具有原子性,即数据库的每一个字段都是不可分割的原子数据项,不能是集合、数组、记录等非原子数据项 当实体中的某个属性有多个值时,必须拆分为不同的属性 例子: 如图…

23.6.23

1.整理用户相关的指令、整理磁盘相关的指令 (1)用户相关 创建用户:sudo adduser 用户名 给新用户添加sudo权限:sudo vim /etc/sudoers 添加后wq!强制退出 删除用户:sudo userdel (-r&#x…

tomcat环境部署

目录 一、安装jdk 1、关闭防火墙,将安装 Tomcat 所需软件包传到/opt目录下,安装JDK 2、设置JDK环境变量 3、使用文本工具编写java源代码 二、安装启动Tomcat 1、解包 2、后台启动 3、使用80端口访问 一、安装jdk 在部署 Tomcat 之前必须安装好…

Java学习629

线程安全 开发中银行排号,火车售票系统中多线程程序发生的问题 引入代码: package Test0626;class SaleTicket implements Runnable{int ticket 100;Overridepublic void run() {while(true){if (ticket > 0){System.out.println(Thread.currentT…

ROS2 launch文件同时引入yaml文件参数和自定义变量参数

0 背景 在ROS中,launch工具可以帮助用户同时启动多个节点,以及引入多种设置如参数导入、节点名重映射等。在ROS1中,launch文件通过xml语言编写,后缀名为.launch;而ROS2在xml的基础上(后缀名为.xml&#xf…

【Servlet学习四】实现一个内存版本的表白墙~

目录 一、前端代码 二、后端代码实现 🌈1、全局类定义AppVar 🌈2、实体类定义Message 🌈3、获取所有信息:getMessageServlet实现前后端的交互 🌈4、添加数据:addMessageServlet,实现前后端…

notepad++去除换行符和空格

在notepad中按Ctrlh 1.去除换行符 输入如图所示的查找内容为\r\n,【替换为】不填写,勾选底部的【正则表达式】,然后点击【全部替换】 2. 按照逗号换行 输入如图所示的查找内容为,,【替换为】\r\n,勾选底部的【正则…

C# WinForm 选择打开文件和保存文件

做 winform 项目的时候正好遇到了记录一下: 打开文件 我们使用 OpenFileDialog 控件来打开文件选择框: 通过 Title 属性可以设置选择框的标题而 Filter 属性可以设置选中的文件类型,这个属性由两个部分组成 SVG files (*.svg)|*.svg &am…

九、云尚办公系统-管理端-审批管理

云尚办公系统:管理端-审批管理 B站直达【为尚硅谷点赞】: https://www.bilibili.com/video/BV1Ya411S7aT 本博文以课程相关为主发布,并且融入了自己的一些看法以及对学习过程中遇见的问题给出相关的解决方法。一起学习一起进步!!…

Unity导出到AS中真机测试apk没有问题,aab提交到GooglePlay审核通过,但是从Google Play下载的应用闪退问题

从Google Play下载的应用报错如下: backtrace: #00 pc 0x0000000000050748 /data/app/~~x94h_Fmdoj4Vj1NVQcL7sQ/com.id.hhhuhi-LpC7BJqILn3X29R8TffhuA/split_config.arm64_v8a.apk!libpairipcore.so (ExecuteProgram196) 06-26 20:39:40.526 13936 13936 F l…

基于Java+Vue前后端分离宠物领养系统设计实现(源码+lw+部署文档+讲解等)

博主介绍:✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专…

ML@集成学习@摘要

文章目录 集成学习refs摘要Note准确性和多样性 集成学习方法分类BoostingAdaBoost伪代码Adaboost小结 补充补充1补充2 BaggingBagging伪代码 特点算法效率直接应用于多分类 自助采样和包外估计随机森林 Stackingsklearn中的Stacking🎈构造初级学习器构造次级学习器 …