Java多线程之死锁详解

网友投稿 248 2022-11-28

Java多线程之死锁详解

目录1、死锁2、死锁经典问题——哲学家就餐问题 总结

1、死锁

出现场景:当线程A拥有了A对象的锁,想要去获取B对象的锁;线程B拥有了B对象的锁,想要拥有A对象的锁,两个线程在获取锁的时候,都不会释放已经持有的锁,于是,就造成了死锁。

示例代码:

@Slf4j

public class ThreadTest {

private static Object objectA = new Object();

phttp://rivate 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(Stringhttp:// 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 + "正在吃饭");

}

}

测试结果:可以实现吃饭操作,但是会出现场景中描述的问题,出现线程死锁。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:家有小伙初长成 -- ASM
下一篇:利用MAX5456/MAX5457构成音量调节器
相关文章

 发表评论

暂时没有评论,来抢沙发吧~