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

所属分类: 软件编程 / java 阅读数: 31
收藏 0 赞 0 分享

本文实例讲述了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程序设计有所帮助。

更多精彩内容其他人还在看

Springmvc restful配置遇到的小坑

本文是小编给大家带了的Springmvc restful配置遇到的小小坑,小编给大家带来了问题原因及解决办法,非常不错,具有参考借鉴价值,感兴趣的朋友一起看下吧
收藏 0 赞 0 分享

Java中的匿名内部类小结

java内部类分为: 成员内部类、静态嵌套类、方法内部类、匿名内部类。这篇文章主要介绍了Java中的匿名内部类的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

Java的云打印Lodop

这篇文章主要介绍了Java的云打印Lodop 的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

Java线程池框架核心代码解析

这篇文章主要针对Java线程池框架核心代码进行详细解析,分析Java线程池框架的实现ThreadPoolExecutor,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Java 交换两个变量的数值实现方法

下面小编就为大家带来一篇Java 交换两个变量的数值实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

全面了解JAVA_BaseDAO数据处理类

下面小编就为大家带来一篇全面了解JAVA_BaseDAO数据处理类。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

java、python、JavaScript以及jquery循环语句的区别

本篇文章主要介绍java、python、JavaScript以及jquery的循环语句的区别,这里整理了它们循环语句语法跟示例,以便大家阅读,更好的区分它们的不同
收藏 0 赞 0 分享

基于JDBC封装的BaseDao(实例代码)

下面小编就为大家带来一篇基于JDBC封装的BaseDao(实例代码)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

简单通用JDBC辅助类封装(实例)

下面小编就为大家带来一篇简单通用JDBC辅助类封装(实例)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

浅谈java线程中生产者与消费者的问题

下面小编就为大家带来一篇浅谈java线程中生产者与消费者的问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享
查看更多