【JavaEE】——多重锁,死锁问题和解决思路

server/2024/10/19 7:31:37/

阿华代码,不是逆风,就是我疯,你们的点赞收藏是我前进最大的动力!!希望本文内容能够帮助到你!

目录

一:加锁的“可重入性”

1:问题引入

2:问题分析

3:可重入性

(1)解释

(2)应用举例

4:内层机制分析

二:死锁

1:情景一

(1)代码解析

2:情景二——N个线程M把锁(进阶)

(1)举例:哲学家吃面条问题

(2)极端情况

(3)产生死锁的四个必要条件

①互斥性

②不可抢占性

③保持性

④循环等待

三:解锁

1:解锁思路

2:指定加锁顺序


引入:通过上一篇文章的学习,我们针对线程安全问题,简单认识了synchronized关键字,给操作“打包”,避免了一些多线程会出现的bug,通过本章学习我们将更进一步的学习Synchronized

一:加锁的“可重入性”

1:问题引入

我们给Thread线程,加两道锁,提问:hello能顺利打印出来吗

java">public class ThreadDemon24 {public static void main(String[] args) {Object locker = new Object();Thread t1 = new Thread(()->{synchronized(locker){synchronized(locker){System.out.println("hello");}}});t1.start();}
}

2:问题分析

问:2已经加锁了,1再尝试加锁,不会出现“阻塞”情况吗?觉得会阻塞的扣1,不会阻塞的扣2~~

恭喜扣2的同学。由于是同一个线程,代码走到1时第一次加锁,走到2时,被加锁的对象locker知道第二次加锁是同一个线程(友军),所以就放行了,不会“阻塞”。

3:可重入性

(1)解释

“可重入性”就是在加锁机制中,同一个对象在同一个线程下第一次加完锁之后,再次遇到该线程下的对该对象的加锁,此时第二次加锁操作就会直接对该对象放行。就不会出现“阻塞”和“死锁”的情况。

(2)应用举例

我们平时写的代码,由于复杂的层层调用,无意中写出了双重加锁(锁重复)的情况,此时加锁的“可重复性”机制就能很好的解决这个问题。

4:内层机制分析

对于“可重入锁”机制来说,内部有两个信息

①当前“锁”是被哪个线程所持有的

②加锁次数的计数器

最外层的   {   这种括号负责加锁

最外层的   }  这种括号负责解锁

注:锁状态是没法直接查看的,我们只能通过jconsole来查看线程的状态,比如:BLOCKED

二:死锁

1:情景一

java">package thread;/*** Created with IntelliJ IDEA.* Description:* User: Hua YY* Date: 2024-09-22* Time: 10:32*/
public class ThreadDemon25 {public static void main(String[] args) {Object A = new Object();Object B = new Object();Thread t1 = new Thread(()->{synchronized(A){try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized(B){System.out.println("尝试获取B锁");}}});Thread t2 = new Thread(()->{synchronized(B){try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized(A){System.out.println("尝试获取A锁");}}});t1.start();t2.start();}
}

(1)代码解析

通过 上面的代码结果的分析,t1和t2线程堵塞了,即t1想要获取B这个对象加锁,但是B已经被t2给锁上了,t2想要获取A这个对象,但是A已经被t1给锁上了。

2:情景二——N个线程M把锁(进阶)

(1)举例:哲学家吃面条问题

(五个滑稽老铁相当于五个线程,五根筷子相当于五把锁)有五个滑稽老铁一起吃面条,每个滑稽间放了一根筷子,比如一号滑稽老铁想要吃面条,就必须同时拿起1、5两根筷子,滑稽老铁吃面条的时候,其它人不能硬抢筷子。

滑稽老铁除了吃面条,就是放下筷子思考人生(线程不工作),由于每位哲学家什么时候吃面条,什么时候思考人生是不确定的(线程的随机调度),所以大部分情况下,筷子是够用的。

(2)极端情况

所有人都想吃面条,同时拿起左手边的筷子,此时想拿右手边的筷子时就g了(没人吃到面,也没人释放筷子,这就成了一个死锁了)

(3)产生死锁的四个必要条件

①互斥性

获取锁的过程是互斥的,一把锁只能被一个线程获取,另一个线程想要获取同一把锁就必须阻塞等待

②不可抢占性

一个线程拿到了锁,除非这个线程主动解锁,否则不会被别的线程强行把锁给抢走

③保持性

一个线程想获取第二把锁,那么第一把锁依旧还是存在的,不会消失

④循环等待

三:解锁

1:解锁思路

只要破坏掉上述产生死锁的四个必要条件中的随便一个,我们就能解锁了

但是①②点都是锁的最基本特性,不好破坏,③得具体情况具体分析,④破坏这种循坏的代码结构是最容易的。

2:指定加锁顺序

针对五把锁进行编号,五个滑稽老铁进行编号,指定一定的规则:先获取编号小的锁,在获取编号大的锁,这样就避免循环等待,避免了死锁。

当然这里还有很多别的方法就不一一赘述了~~

 


http://www.ppmy.cn/server/123100.html

相关文章

提升微信管理效率:自动回复功能解析

在快节奏的数字时代,高效的沟通工具对于管理多个微信账号至关重要。古人云:“工欲善其事,必先利其器”,这句话在今天依然适用。微信自动回复功能正是这样的“利器”,它能够显著提升微信管理的效率和用户体验。 自动通过…

力扣 简单 112.路径总和

文章目录 题目介绍题解 题目介绍 题解 class Solution {public boolean hasPathSum(TreeNode root, int targetSum) {// 只在最开始的时候判断树是否为空if (root null) {return false;}targetSum - root.val;if (root.left null && root.right null) { // root 是…

grafana加载缓慢解决方案

背景 目前随着数据和图表的逐渐增多,Grafana 页面加载速度明显变慢,严重影响了用户体验,几次都有骂娘的冲动.,因此我们需要对 Grafana 进行优化,以提升加载性能。 对于速度优化,我们可以从以下方面进行入…

【JavaEE】——内存可见性问题

阿华代码,不是逆风,就是我疯,你们的点赞收藏是我前进最大的动力!!希望本文内容能够帮助到你! 目录 一:内存可见性问题 1:代码解释 2:结果分析 (1&#xf…

多线程事务管理:Spring Boot 实现全局事务回滚

多线程事务管理:Spring Boot 实现全局事务回滚 在日常开发中,我们常常会遇到需要在多线程环境下进行数据库操作的场景。这类操作的挑战在于如何保证多个线程中的数据库操作要么一起成功,要么一起失败,即 事务的原子性。尤其是在多个线程并发执行的情况下,确保事务的一致性…

速盾:cdn是怎么加速视频的?

CDN(Content Delivery Network)是一种网络加速服务,通过将内容分发到全球各地的服务器节点上,提供更快速度和更可靠的内容传输。当涉及到视频内容时,CDN起到了至关重要的作用,它通过一系列的技术和策略来加…

IDEA2020运行项目时不从配置的maven仓库找jar包,从C盘默认路径下找jar包

目录 问题描述: 解决方案: 问题描述: 使用IDEA2020做java开发,idea的设置中maven仓库地址配在D盘, maven的配置文件setting.xml中的仓库也已经确认配置到D盘, 项目根据pom文件自动下载jar包时也会下载到…

网络安全入门教程(非常详细)从零基础入门到精通,看完这一篇就够了。

学前感言: 1.这是一条坚持的道路,三分钟的热情可以放弃往下看了.2.多练多想,不要离开了教程什么都不会了.最好看完教程自己独立完成技术方面的开发.3.有时多google,baidu,我们往往都遇不到好心的大神,谁会无聊天天给你做解答.4.遇到实在搞不懂的,可以先放放,以后再来解决. 基…