<多线程章节五>synchrosized的可重入特性

news2024/11/15 16:00:38

💐专栏导读

本篇文章收录于多线程,也欢迎翻阅博主的其他文章,可能也会让你有不一样的收获😄
🍁JavaSE 🌺多线程 🍂数据结构

💐synchrosized的可重入特性及死锁

可重入特性就是:当一个线程针对一个对象同时加锁两次,不会构成死锁,这样的特性称为可重入性;

例如下图例子:

在这里插入图片描述

为了防止上述死锁情况,synchrosized就引入了可重入性解决;

线程在加锁时,在这个锁对象内部,它会记录是对哪个线程加了锁,当对同一个线程再次进行加锁时,就会判断该线程是不是同一个线程并且是否已经持有了锁,如果已经有了锁,那么也会重复进行加锁,不会导致死锁现象;

**那么,问题就来了,如果加两次锁,在 }2 时是否应该解锁呢?**答案:不能释放锁

在这里插入图片描述

如果加了n次锁呢?该怎么去释放呢?

答案:在锁对象中,不仅会记录对哪个线程加了锁,还会有一个计数器记录加锁的次数;当每次执行完一个加锁的代码块时,计数器就会减1,一直到最后一个锁时,才会释放锁;

关于死锁:

1.在Java中,如果一个线程对同一个锁连续加锁两次,不会造成死锁现象

2.如果两个线程,两把锁,每个线程都加两个不同的锁(嵌套加锁),就会造成死锁现象

例如:让线程1先获取锁1,线程2获取锁2,然后在锁1的内部再尝试获取锁2, 再锁2的内部再尝试获取锁1

public static void main(String[] args) {
        //定义两把锁
        Object lock1 = new Object();
        Object lock2 = new Object();
        //让线程1嵌套获取两把锁
        Thread thread1 = new Thread(() -> {
            synchronized (lock1) {
                //此处睡眠很重要,如果没有睡眠,线程1可能就会一下子把两把锁都获取了,就构不成死锁现象了
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                
                synchronized (lock2) {
                    System.out.println("thread1加锁成功");
                }
            }
        });
        //让线程2嵌套获取两把锁
        Thread thread2 = new Thread(() -> {
            synchronized (lock2) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                synchronized (lock1) {
                    System.out.println("thread2加锁成功");
                }
            }
        });
        thread1.start();
        thread2.start();
    }

在这里插入图片描述

3.n个线程,m把锁,更容易出现死锁问题,例如哲学家就餐问题:

哲学家就餐问题:

在这里插入图片描述

死锁是一个比较严重的bug,那如何避免/解决死锁呢?

💡如何避免/解决死锁

要想避免死锁,就要先直到死锁是怎么形成的,这样才能对症下药,导致死锁的四个必要条件:

1.互斥使用:当线程1获取锁之后,线程2也想获取同一把锁,就会阻塞等待(锁的特性)

2.不可抢占:当线程1已经获取到锁之后,线程2不能强行抢占锁(锁的特性)

3.请求保持:一个线程尝试获取多把锁(一个线程获取到锁1之后,还想尝试获取锁2,此时锁1也并未解锁)例如上面的

4.循环等待:线程获取锁时,形成了环路;例如,上面哲学家同时拿起左边的筷子

第一点和第二点是锁的特性,如果想要解决死锁,就要破坏第三点和第四点,

对于第三点来讲,只要避免两把不同的锁嵌套获取即可

在这里插入图片描述

对于第四点来讲,可以约定给所有的锁进行一个编号,规定所有的线程只能按顺序先获取编号小的锁,然后获取编号大的锁,例如:

在这里插入图片描述

在这里插入图片描述

以上虽然时嵌套加锁的,但是并未形成环路,得到lock1锁的线程执行,未获得lock1的线程阻塞等待,并且也无法获得lock2

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

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

相关文章

汉威科技光纤预警系统,守护油气长输管道“大动脉”

石油、天然气早已成为城市生活中不可或缺的能源。广大车主能快速地加上汽油,千家万户能方便地用上天然气,得益于我国庞大的石油、天然气输送基础设施网络。 我国油气分布西多东少、北多南少,要想把千里、乃至万里之外的石油、天然气输送到中部…

降本增效的集成平台

降本增效的集成平台是企业数字化转型中的关键工具之一。它能够帮助企业解决传统集成方式面临的痛点,并满足企业在数字化转型过程中的需求。下面将重点讲解企业集成的痛点及需求、传统与全域集成的对比。 企业集成的痛点及需求: 系统孤岛和信息孤岛&…

uniapp vue2、vue3 页面模板代码块设置

本文分享 uniapp vue2、vue3 页面模板代码块设置 设置路径 HBuilder X -> 工具 -> 代码块设置 -> vue代码块 -> 自定义代码块 如上图操作后在打开的 vue.json 文件的右侧“自定义代码块”中复制如下代码(可全选替换也可添加到代码中) 示…

为何开发需要更多地考虑运维便利性

在当前的软件行业中,开发和运维是两个不可或缺的环节。然而,有时候我们会发现,一些软件开发人员过于关注开发的便捷性,而忽视了运维部署的复杂性。这种做法可能会导致开发出的软件部署难度大,甚至容易出现问题。因此&a…

【赠书活动】国家数据局正式揭牌,数据专业融合型人才迎来发展良机

摘要:新华社北京10月26日电 《中国证券报》26日刊发文章《国家数据局揭牌 数据要素产业进入加速发展期》。文章称,10月25日,国家数据局正式揭牌。业内人士认为,这标志着我国数字经济发展新阶段的开始,预计数据要素配套…

【数据结构】数组和字符串(七):特殊矩阵的压缩存储:三元组表的转置、加法、乘法操作

文章目录 4.2.1 矩阵的数组表示4.2.2 特殊矩阵的压缩存储a. 对角矩阵的压缩存储b~c. 三角、对称矩阵的压缩存储d. 稀疏矩阵的压缩存储——三元组表4.2.3三元组表的转置、加法、乘法、操作转置加法乘法算法测试实验结果代码整合 4.2.1 矩阵的数组表示 【数据结构】数组和字符串…

Linux | 进程地址空间

目录 前言 一、初始进程地址空间 1、实验引入 2、虚拟地址空间 二、什么是进程地址空间 1、基本概念 2、深入理解进程地址空间 3、进程地址空间的本质 4、遗留问题解决 三、为什么要有进程地址空间 1、知识扩展 2、进程地址空间存在意义 3、重新理解挂起 前言 本…

[SQL开发笔记]SQL 别名:为表名称或列名称指定别名

一、功能描述: 通过使用 SQL,可以为表名称或列名称指定别名。基本上,创建别名是为了让列名称的可读性更强。 二、SQL 别名语法详解: (1)列的 SQL 别名语法: Select column_name AS alias_nam…

X86(32位)汇编指令与机器码转换原理

X86(32位)汇编指令与机器码转换原理 1 32位寻址形式下的ModR/M字节2 汇编指令转机器码2.1 mov ecx,[eaxebx*2]2.1.1 查Opcode和ModR/M2.1.2 查SIB 2.2 mov ecx,[eaxebx*210h]2.3 mov ecx,[eaxebx*200000100h] 本文属于《 X86指令基础系列教程》之一&…

Spring Cloud Gateway + Knife4j 4.3 接口文档整合和网关聚合

目录 前言Spring Cloud 整合 Knife4jpom.xmlapplication.ymlSwaggerConfig.java访问单服务接口文档 Spring Cloud Gateway 网关聚合pom.xmlapplication.yml访问网关聚合接口文档 接口测试**登录认证**获取登录用户信息 结语源码 前言 youlai-mall 开源微服务商城新版本基于 Sp…

数据库SqlServer笔试题

数据库SqlServer笔试题 一、数据库基础知识(通用)篇 1.说说主键、外键、超键、候选键 超键:在关系中能唯一标识元组的属性集称为关系模式的超键。一个属性可以为作为一个超键,多个属 性组合在一起也可以作为一个超键。超键包含…

CSGO游戏搬砖的10个冷知识,90%的人还不知道

敲黑板了,同学们,很多人号一多就蒙圈,接下来解释一下buff号、Steam号、选品软件、识别码,桌面令牌,手机令牌,几者的关系: 1、前期一套实名只能绑定两个buff号,steam账号无需实名,后期…

安装和配置Maven,IDEA中配置Maven

一、安装 Maven 首先创建一个空的文件夹,文件夹不能是中文或者其他特殊字符,然后将maven文件解压到这个空的文件夹 解压 二、配置环境变量 电脑右键 高级系统设置 输入以下内容 编辑好之后一直点击确定 验证是否安装成功,winR输入cmd进入命令…

docker 部署 若依 Ruoyi springboot+vue分离版

本篇从已有虚拟机/服务器 安装好dokcer为基础开始讲解 1.部署mysql 创建conf data init三个文件夹 conf目录存放在mysql配置文件 init目录存放着若依数据库sql文件(从navicat导出的并非若依框架自带sql) 创建一个属于本次若依部署的网段(只…

nc65单据穿透

nc65单据穿透 jych项目 1.支出合同台账合同号字段可以穿透到对应的单据上 一个合同号穿透到一个物质设备采购合同上 1.支出合同台账单据模板合同号字段卡片下和列表下高级属性勾选是否超链接 2.支出合同台账中增加监听类 HeadItemLinkListener.java package nc.ui.jych.…

如何处理 Python 报错 can‘t multiply sequence by non-int of type float

大多数时候,当你在编程时遇到错误,你可以在错误信息中发现错误发生的原因以及如何解决它。 Python 错误 “TypeError: can’t multiply sequence by non-int of type float” 也不例外。 我准备了这篇文章,向你展示这个错误发生的原因以及如…

目标检测及锚框、IoU

1. 目标检测 物体检测(目标检测)是计算机视觉和数字图像处理的热门方向,意在判断一幅图像上是否存在感兴趣物体,并给出物体分类及位置等(What and Where)。本文主要进行物体检测研究背景、发展脉络、相关算…

MySQL的概念和sql语句

数据库的概念 数据库的概念:数据库是用来组织(各个数据之间是有关联,是按规则组织起来的),存储和管理(增,删,改,查)的仓库 数据库管理系统(DBMS&…

写保护设置——三、I2C EEPROM

三、I2C EEPROM I2C通讯的EEPROM只有硬保护,没有软保护。 以AT24C01A/02/04/16型EEPROM和AT24C02A/04A/08A/16A型EEPROM为例,管脚定义和写保护WP功能分别如下。 (1)AT24C01A/02/04/16型EEPROM 规格书: AT24C01A/02…

软件测试行情不好,我还是啃下了27K的offer

o “会代码吗?” o “会,Java、Python我都会一些!” o “有没有用代码开发过一些测试工具平台呢?” o “额。。。这个。。。没做过。。。” o “那你回去等消息吧” 软件测试行业发展到今天,测试人员会代码&#x…