服务器之家

服务器之家 > 正文

Java多线程之死锁详解

时间:2022-03-01 00:36     来源/作者:不关阿强的事

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系统搜索就可以,打开是这个样子。

Java多线程之死锁详解

然后在本地进程里面选择你的进程,其实就是你的项目名称。然后点击连接,在点击不安全连接。

​​​​​​​Java多线程之死锁详解

进去之后点击线程

Java多线程之死锁详解

再点击检测死锁

Java多线程之死锁详解

最后就能看到死锁的线程了

Java多线程之死锁详解

(2)首先是在idea的控制台,打开Terminal,输入【jps】命令查看所有的进程id,找到你自己的java类名称对应的id。

然后输入【jstack + 进程号】 就可以查询到该进程的所有线程信息。在输出信息的最下面,就可以看到如下图所示的线程死锁信息。

Java多线程之死锁详解

 

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 + "正在吃饭");
  }
}

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

Java多线程之死锁详解

 

总结

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

原文链接:https://blog.csdn.net/qq_42251944/article/details/120879781

标签:

相关文章

热门资讯

2022年最旺的微信头像大全 微信头像2022年最新版图片
2022年最旺的微信头像大全 微信头像2022年最新版图片 2022-01-10
蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整
蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整 2021-08-24
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
返回顶部