Java模拟死锁发生之演绎哲学家进餐问题案例详解

 更新时间:2019年10月23日 09:09:21   作者:cakincqm  
这篇文章主要介绍了Java模拟死锁发生之演绎哲学家进餐问题,结合具体演绎哲学家进餐问题的案例形式详细分析了死锁机制与原理,需要的朋友可以参考下

本文实例讲述了Java模拟死锁发生之演绎哲学家进餐问题。分享给大家供大家参考,具体如下:

一 点睛

常见的死锁形式:当线程1已经占据资源R1,并持有资源R1上的锁,而且还在等待资源R2的锁;而线程2已经占据资源R2,并且持有资源R2上的锁,却正在等待资源R1上的锁。如果两个线程不释放自己占据的资源锁,而且还申请对方资源上的锁,申请不到时只能等待,而且它们只能永远的等待下去。

二 实战

1 代码

public class DeadLockDemo
{
  /** knife锁 */
  private static String knife = "餐刀"; //临界资源
  /** fork锁 */
  private static String fork = "叉子"; //临界资源
  public static void main(String[] args)
  {
    DaemonThread daemonTh = new DaemonThread();
    Thread newDaemon = new Thread(daemonTh);
    newDaemon.setDaemon(true);
    newDaemon.start();
    new DeadLockDemo().deadLock();
  }
  private void deadLock()
  {
    Thread t1 = new Thread(new Runnable() {
      @Override
      public void run()
      {
        synchronized (knife) {
          System.out.println(Thread.currentThread().getName() + "拿起了" + knife + ", 等待" + fork + "......");
          try {
            Thread.sleep(2000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          synchronized (fork) {
            System.out.println(Thread.currentThread().getName() + "又拿起了" + fork + ",吃饭中...");
          }
        }
      }
    });
    Thread t2 = new Thread(new Runnable() {
      @Override
      public void run() {
        synchronized (fork) {
          System.out.println(Thread.currentThread().getName() + "拿起了" + fork + ", 等待" + knife + "......");
          synchronized (knife) {
            System.out.println(Thread.currentThread().getName() + "又拿起了" + knife + ",吃饭中...");
          }
        }
      }
    });
    t1.start();
    t2.start();
  }
}
class DaemonThread implements Runnable
{
  @Override
  public void run()
  {
    while(true)
    {
      try {
        Thread.sleep(1000);
      }catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("守护线程:程序仍在运行中...");
    }
  }
}

2 运行

Thread-1拿起了餐刀, 等待叉子......
Thread-2拿起了叉子, 等待餐刀......
守护线程:程序仍在运行中...
守护线程:程序仍在运行中...
守护线程:程序仍在运行中...
守护线程:程序仍在运行中...
守护线程:程序仍在运行中...

三 预防死锁

1 解决方法

如果规定线程A和B都必须先拿刀,再拿叉,就不会发生死锁。

2 代码

public class DeadLockDemo
{
  /** knife锁 */
  private static String knife = "餐刀"; //临界资源
  /** fork锁 */
  private static String fork = "叉子"; //临界资源
  public static void main(String[] args)
  {
    DaemonThread daemonTh = new DaemonThread();
    Thread newDaemon = new Thread(daemonTh);
    newDaemon.setDaemon(true);
    newDaemon.start();
    new DeadLockDemo().deadLock();
  }
  private void deadLock()
  {
    Thread t1 = new Thread(new Runnable() {
      @Override
      public void run()
      {
        synchronized (knife) {
          System.out.println(Thread.currentThread().getName() + "拿起了" + knife + ", 等待" + fork + "......");
          try {
            Thread.sleep(2000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          synchronized (fork) {
            System.out.println(Thread.currentThread().getName() + "又拿起了" + fork + ",吃饭中...");
          }
        }
      }
    });
    Thread t2 = new Thread(new Runnable() {
      @Override
      public void run() {
        synchronized (knife) {
          System.out.println(Thread.currentThread().getName() + "拿起了" + knife + ", 等待" + fork + "......");
          synchronized (fork) {
            System.out.println(Thread.currentThread().getName() + "又拿起了" + fork + ",吃饭中...");
          }
        }
      }
    });
    t1.start();
    t2.start();
  }
}
class DaemonThread implements Runnable
{
  @Override
  public void run()
  {
    while(true)
    {
      try {
        Thread.sleep(1000);
      }catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("守护线程:程序仍在运行中...");
    }
  }
}

3 运行

Thread-1拿起了餐刀, 等待叉子......
守护线程:程序仍在运行中...
守护线程:程序仍在运行中...
Thread-1又拿起了叉子,吃饭中...
Thread-2拿起了餐刀, 等待叉子......
Thread-2又拿起了叉子,吃饭中...

更多java相关内容感兴趣的读者可查看本站专题:《Java进程与线程操作技巧总结》、《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总

希望本文所述对大家java程序设计有所帮助。

相关文章

  • Mybatis-Plus处理Mysql Json类型字段的详细教程

    Mybatis-Plus处理Mysql Json类型字段的详细教程

    这篇文章主要给大家介绍了关于Mybatis-Plus处理Mysql Json类型字段的详细教程,Mybatis-Plus可以很方便地处理JSON字段,在实体类中可以使用@JSONField注解来标记JSON字段,同时在mapper.xml中使用json函数来操作JSON字段,需要的朋友可以参考下
    2024-01-01
  • Java 自定义注解及利用反射读取注解的实例

    Java 自定义注解及利用反射读取注解的实例

    下面小编就为大家带来一篇Java 自定义注解及利用反射读取注解的实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • java使用RSA与AES加密解密的实例代码详解

    java使用RSA与AES加密解密的实例代码详解

    这篇文章主要介绍了java使用RSA与AES加密解密的实例代码,代码简单易懂,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-06-06
  • Java 括号匹配问题案例详解

    Java 括号匹配问题案例详解

    这篇文章主要介绍了Java 括号匹配问题案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • java虚拟机深入学习之内存管理机制

    java虚拟机深入学习之内存管理机制

    java虚拟机在程序运行时将内存划分为多个区域,每个区域作用,生命周期各不相同,下面这篇文章主要给大家介绍了关于java虚拟机深入学习之内存管理机制的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2018-11-11
  • Mybatis使用MySQL模糊查询时输入中文检索不到结果怎么办

    Mybatis使用MySQL模糊查询时输入中文检索不到结果怎么办

    这篇文章主要介绍了Mybatis使用MySQL模糊查询时输入中文检索不到结果的解决办法的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-07-07
  • SpringBoot集成JPA的示例代码

    SpringBoot集成JPA的示例代码

    本篇文章主要介绍了SpringBoot集成JPA的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • 基于Java实现五子棋小游戏(附源码)

    基于Java实现五子棋小游戏(附源码)

    这篇文章主要为大家介绍了如何通过Java实现简单的五子棋游戏,文中的示例代码讲解详细,对我们学习Java游戏开发有一定帮助,需要的可以参考一下
    2022-11-11
  • Java实现断点下载服务端与客户端的示例代码

    Java实现断点下载服务端与客户端的示例代码

    这篇文章主要为大家介绍了如何实现服务端(Spring Boot)与客户端(Android)的断点下载与下载续传功能,文中的示例代码讲解详细,需要的可以参考一下
    2022-08-08
  • 如何调试报表插件

    如何调试报表插件

    在项目开发过程中插件调试非常的麻烦,需要修改里面的代码,编译出class,需要重新打包插件。然后把之前的删除,重新安装最新的。调试过程比较繁琐,而且不能调试,十分的不方便,这篇文章主要介绍的是调试报表插件的方法,需要的朋友可以参考下
    2015-07-07

最新评论