【问题标题】:How to solve Dining Philosophers with Mutex in Java?如何在 Java 中使用 Mutex 解决餐饮哲学家的问题?
【发布时间】:2012-12-25 21:25:47
【问题描述】:

我的 java 项目有 3 个 java 类。有 Main、Philosoper 和 chStick。我使用布尔值 isTaken 解决了餐饮哲学家问题。

在项目 chStick.java 中,如下所示。该类控制筷子使用或不使用。

class ChStick
{
   private int id;
   private boolean isTaken;

   ChStick (int id)
   {  
       this.id=id;
   }

   synchronized void get () throws InterruptedException
   {
       while(isTaken){
          wait();
       }

       isTaken=true;
   }

   int getID ()
   {
       return id;
   }

   synchronized void put () throws InterruptedException
   {
      isTaken=false;
   }
}

此代码成功运行。当我使用信号量而不是布尔值 isTaken 时,它也成功运行。

我的问题是使用 Mutex 重写这个类。我尝试了很多方法,但仍然没有奏效。它必须使用 Mutex 类。

编辑:

class Philos extends Thread// #9 - Make this class to be inherited from Thread class
{
   private String name;
   private ChStick left, right;

   Philos (String name, ChStick left, ChStick right)
   {
     // #10 - Assign this philosopher a name, his left and rigt chopsticks.
       this.left=left;
       this.right=right;
       this.name=name;
   }

    @Override
   public void run ()
   {
       while (true)
       {
          try
          {
              System.out.println ("Philosopher " + name + " is thinking.");

              // #11 - Make philosopher sleep for a RANDOM time.
              Thread.sleep(1000);

              System.out.println ("Philosopher " + name + " is hungry.");



              if (left.getID () < right.getID ())
              {
                  System.out.println ("Philosopher " + name +
                                      " getting left ChStick.");

            // #12 - Make philosopher to get left chopstick.
                  left.get();

                  System.out.println ("Philosopher " + name +
                                      " got left ChStick."+left.getID());
              }
              else
              {
                  System.out.println ("Philosopher " + name +
                                      " getting right ChStick.");

                  // #13 - Make philosopher to get right chopstick.
                  right.get();

                  System.out.println ("Philosopher " + name +
                                      " got right ChStick."+right.getID());
              }

              // Get other ChStick.

              if (left.getID () < right.getID ())
              {
                  System.out.println ("Philosopher " + name +
                                      " getting right ChStick.");

            // #14 - Make philosopher to get (left or right)? chopstick.
                  right.get();

                  System.out.println ("Philosopher " + name +
                                      " got right ChStick."+right.getID());
              }
              else
              {
                  System.out.println ("Philosopher " + name +
                                      " getting left ChStick.");

                  // #15 - Make philosopher to get (left or right)? chopstick.
                  left.get();


                  System.out.println ("Philosopher " + name +
                                      " got left ChStick."+left.getID());
              }

              System.out.println ("Philosopher " + name + " is eating.");

              // #16 - Make philosopher sleep for a RANDOM time.
              Thread.sleep(2000);

              // #17 - Make philosopher to put the left chopstick down.

              System.out.println ("Philosopher " + name +
                                  " putting down left ChStick."+left.getID());
              left.put();

              // #17 - Make philosopher to put the right chopstick down.

              System.out.println ("Philosopher " + name +
                                  " putting down right ChStick."+right.getID());
              right.put();
          } 
          catch (InterruptedException e) {}
       }
   }
}



public class Main
{
   public static void main (String [] args)
   {                                                 

    // #1 - Here you should create chopstick instances 
    //      and number them using the structure defined in its class definition. 

    // ChStick cs1 = new ChStick ..
       ChStick cs1 = new ChStick(1);
       ChStick cs2 = new ChStick(2);
       ChStick cs3 = new ChStick(3);
       ChStick cs4 = new ChStick(4);
       ChStick cs5 = new ChStick(5);


    // #2 - Here you should create Philosopher instances
    //      and assign them names, their right and left chopsticks.
    //      BE CAREFUL IN WHICH ORDER THEY SIT AROUND THE TABLE 

    // Philos p1 = new Philos ("P1"...)
      Philos p1 = new Philos("P1",cs1,cs5);
      Philos p2 = new Philos("P2",cs2,cs1);
      Philos p3 = new Philos("P3",cs3,cs2);
      Philos p4 = new Philos("P4",cs4,cs3); 
      Philos p5 = new Philos("P5",cs5,cs4);

    // #3 - Start p
      p1.start();
      p2.start();
      p3.start();
      p4.start();
      p5.start();
   }
}

【问题讨论】:

  • Java标准库中没有Mutex类。
  • 是的,我知道,但是有 Mutex 类 kickjava.com/src/javax/concurrent/Mutex.java.htm
  • @Marko Topolnik 你显然是对的,但是有一个 Semaphore 类。如果你有一个只有 1 个许可的信号量,那么你基本上有一个互斥体。
  • @bowmore OP 似乎知道 Semaphore 并且它对他有用。
  • 我已经使用了一个只有 1 个许可证的信号量类,我知道它是一个互斥体。但我必须使用 Mutex 类。导入 com.sun.corba.se.impl.orbutil.concurrent.Mutex; Mutex 类的这个导入

标签: java mutex dining-philosopher


【解决方案1】:

我猜你正在寻找的是 Conductor solution 的变体。

您的互斥体将充当指挥者,但一次只允许一位哲学家拿叉子吃饭。

所以任何 phislopher 线程都会在互斥锁上等待成功的 acquire(),使用叉子,因为没有其他哲学家在用餐,所以叉子必须可用。然后吃饭,放下叉子,在互斥体上调用release()

【讨论】:

  • 我在帖子中添加了其他课程。你可以检查。我确实像你对信号量所说的那样。但是如何使用 Mutex 类更改我的代码?
  • ChStick 类应该用 Mutex 替换布尔 isTaken,get() 调用acquire()put() 调用release()。然后您的代码将暴露死锁问题。届时,您可以按照我的回答中描述的方式引入导体来解决死锁。
  • 我无法解决问题@bowmore。我不明白介绍指挥。
  • 我已经获取了你的代码,并为筷子添加了 Mutex,并添加了 Conductor 以解决僵局:这是一个 pastebin pastebin.com/3Xiuv9Vf
  • @bownmore 非常感谢。你的指挥课解决了死锁问题,我知道该怎么做。感谢您的关注。
猜你喜欢
  • 2016-03-04
  • 2019-02-07
  • 2010-10-11
  • 2010-10-26
  • 1970-01-01
  • 2017-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多