Java模拟死锁发生之演绎哲学家进餐问题的示例分析
更新:HHH   时间:2023-1-8


这篇文章主要介绍了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模拟死锁发生之演绎哲学家进餐问题的示例分析”这篇文章对大家有帮助,同时也希望大家多多支持天达云,关注天达云行业资讯频道,更多相关知识等着你来学习!

返回编程语言教程...