synchrosized 的可重入特性、死锁、哲学家就餐问题以及解决死锁的方法等干货

文章目录

  • 💐synchrosized的可重入特性
  • 关于死锁:
  • 哲学家就餐问题
  • 💡如何避免/解决死锁

💐synchrosized的可重入特性

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

例如下图:

在这里插入图片描述

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

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

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

在这里插入图片描述

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

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

关于死锁:

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

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

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

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.hqwc.cn/news/506118.html

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

相关文章

NoSQL--虚拟机网络配置

目录 1.初识NoSQL 1.1 NoSQL之虚拟机网络配置 1.1.1 首先,导入预先配置好的NoSQL版本到VMware Workstation中 1.1.2 开启虚拟机操作: 1.1.2.1 点击开启虚拟机: 1.1.2.2 默认选择回车CentOS Linux(3.10.0-1127.e17.x86_64) 7 …

今日Arxiv最热NLP大模型论文:Llama-2上下文扩大48倍的方法来了,港大发布,无需训练

引言:大语言模型的长上下文理解能力 在当今的人工智能领域,大语言模型(Large Language Models,简称LLMs)的长上下文理解能力成为了一个重要的研究方向。这种能力对于模型来说至关重要,因为它使得LLMs能够有…

精品SSM的教学管理系统课程作业成绩

《[含文档PPT源码等]精品基于SSM的教学管理系统[包运行成功]》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功! 软件开发环境及开发工具: Java——涉及技术: 前端使用技术:HTML5,CSS3、Jav…

<网络安全>《63 微课堂<第3课 旁路部署和串行部署是什么?>》

1、串联和并联概念 串联和并联是物理学上的概念。 串联电路把元件逐个顺次连接起来组成的电路。如图,特点是:流过一个元件的电流同时也流过另一个。 并联电路把元件并列地连接起来组成的电路,如图,特点是:干路的电流…

Ps:快照

“历史记录” History面板可分为快照区和历史记录状态区两个部分。 Photoshop 的快照 snapshot功能允许用户保存当前工作状态的完整副本,这包括图像的所有图层(包括图层可见性)、图层样式、选区以及颜色模式、位深度等其他属性。 通过创建当前…

一份在互联网公司干了八年的经验分享

一份在互联网公司干了八年的经验分享 一晃在这一行已经摸爬滚打8年有余,虽科班毕业,也不是什么名校,学校的计算机氛围没那么浓厚,我基本上是在工作之后才开始正儿八经的学习编程,一边啃书本敲代码,一边是上…

汽车三元催化器的废品项目详解,三元催化再生项目的回收技术教学

一、教程描述 这是一个收废品项目,就收那些别人不懂的,三元催化器的附加值高,只要掌握技术,怎么玩都行的,只是要放得下你的面子。三元催化器,是安装在汽车排气系统中最重要的机外净化装置,它可…

NOC2023软件创意编程(学而思赛道)python小高组初赛真题

软件创意编程 一、参赛范围 1.参赛组别:小学低年级组(1-3 年级)、小学高年级组(4-6 年级)、初中组。 2.参赛人数:1 人。 3.指导教师:1 人(可空缺)。 4.每人限参加 1 个赛项。 组别确定:以地方教育行政主管部门(教委、教育厅、教育局) 认定的选手所属学段为准。 二、…

2024年3月5-7日年生物发酵装备展-环科环保科技

参展企业介绍 山东环科环保科技有限公司,是一家集环保设备的设计、制造、安装、服务及环境治理工程总承包于一体的企业。 公司长期专注于大气、水、危固废三大领域,以科技创造碧水蓝天,为客户提供环保解决方案。 以稳定的产品及服务质量、适用的技术、…

BUUCTF---数据包中的线索1

1.题目描述 2.下载附件,是一个.pcap文件 3.放在wireshark中,仔细观察数据流,会发现有个叫fenxi.php的数据流 4.这条数据流是http,且使用GET方式,接下来我们使用http.request,methodGET 命令来过滤数据流 5.在分析栏中我们追踪htt…

DataGrip(IDEA 内置)连接 SQL Server

原文:https://blog.iyatt.com/?p14265 测试环境: IDEA 2023.1SQL Server 2022 首先打开 SQL Server 配置管理工具 启用 TCP/IP 打开 Windows 服务管理 在服务列表中找到 SQL Server(MSSQLSERVER),右键重新启…

C++复习笔记——多态

1 多态 基本概念: 静态多态:编译时多态,运算符重载和函数重载动态多态:运行时多态,派生类重写基类的虚函数实现 静态多态和动态多态的区别就是函数地址是早绑定(静态联编,静态绑定)还是晚绑定(动态联编&a…