Java多线程之死锁 Java多线程之死锁详解
不关阿强的事 人气:0想了解Java多线程之死锁详解的相关内容吗,不关阿强的事在本文为您仔细讲解Java多线程之死锁的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:Java多线程,Java死锁,下面大家一起来学习吧。
1、死锁
出现场景:当线程A拥有了A对象的锁,想要去获取B对象的锁;线程B拥有了B对象的锁,想要拥有A对象的锁,两个线程在获取锁的时候,都不会释放已经持有的锁,于是,就造成了死锁。
示例代码:
@Slf4j public class ThreadTest { private static Object objectA = new Object(); private static Object objectB = new Object(); public static void main(String[] args) throws InterruptedException { Thread t2 = new Thread(()->{ synchronized (objectA){ log.debug("线程t2获取到了objectA"); synchronized (objectB){ log.debug("线程t2获取到了objectB"); } } },"t2"); Thread t1 = new Thread(()->{ synchronized (objectB){ log.debug("线程t1获取到了objectB"); synchronized (objectA){ log.debug("线程t1获取到了objectA"); } } },"t1"); t2.start(); t1.start(); } }
如何检测死锁:
两种方法
(1)找到本机jconsole程序,直接在windows系统搜索就可以,打开是这个样子。
然后在本地进程里面选择你的进程,其实就是你的项目名称。然后点击连接,在点击不安全连接。
进去之后点击线程
再点击检测死锁
最后就能看到死锁的线程了
(2)首先是在idea的控制台,打开Terminal,输入【jps】命令查看所有的进程id,找到你自己的java类名称对应的id。
然后输入【jstack + 进程号】 就可以查询到该进程的所有线程信息。在输出信息的最下面,就可以看到如下图所示的线程死锁信息。
2、死锁经典问题——哲学家就餐问题
经典场景:有四位哲学及在一正方形的桌子上面吃饭,桌子的每个角有一根筷子,一共四根,那么,当每个哲学家都拿起自己左边的筷子之后,再去拿自己右边的筷子的时候,就会发现自己右边没有筷子,这时哲学就就会等右边的哲学家放下筷子,但是每个哲学家都是这个想法,那么都不会放下筷子,并且都拿不到右边的筷子,因此就造成了死锁。
代码实现例子:
@Slf4j public class Thread1 { public static void main(String[] args) throws InterruptedException { //筷子对象 Chopsticks c1 = new Chopsticks("c1"); Chopsticks c2 = new Chopsticks("c2"); Chopsticks c3 = new Chopsticks("c3"); Chopsticks c4 = new Chopsticks("c4"); new Philosopher("李云龙",c1,c2).start(); new Philosopher("赵刚",c2,c3).start(); new Philosopher("魏和尚",c3,c4).start(); new Philosopher("张大彪",c4,c1).start(); } } //筷子 class Chopsticks{ private String name; public Chopsticks(String name) { this.name = name; } } //哲学家 @Slf4j class Philosopher extends Thread{ //名字 private String name; //筷子 private Chopsticks left; private Chopsticks right; public Philosopher(String name, Chopsticks left, Chopsticks right) { super(name); this.left = left; this.right = right; } @Override public void run() { while(true){ synchronized (right){ synchronized (left){ eat(name); } } } } private void eat(String name){ log.debug(name + "正在吃饭"); } }
测试结果:可以实现吃饭操作,但是会出现场景中描述的问题,出现线程死锁。
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注的更多内容!
加载全部内容