0

我一直在从事哲学家就餐任务,但我遇到了一个问题,我的代码围绕 3 个类,叉子、哲学家和 dinerTable(是的,我错误地用小写字母命名了最后两个)。

代码正常启动,哲学家 0 和 2 抓住他们的叉子,但随后代码停止了,谁能帮帮我吗?

有3类:

叉子(扩展线程):

public synchronized boolean isFree() throws InterruptedException
{
    return available;

}

public synchronized void returnFork() throws InterruptedException
{
    available = true;
    this.notify();
}

public synchronized void takeFork() throws InterruptedException
{
    available = false;
    this.notify();
}

哲学家(实现可运行):

    private int number;
private Forks right;
private Forks left;
private boolean hasBothForks;
private boolean keepGoing;

public boolean isKeepGoing() {
    return keepGoing;
}

public void setKeepGoing(boolean keepGoing) {
    this.keepGoing = keepGoing;
}

public philosophers(int number,Forks right, Forks left, boolean keepGoing)
{
    this.number = number;
    this.right = right;
    this.left = left;
    hasBothForks = false;
    this.keepGoing = keepGoing;
}

private void print(String message)
{
    System.out.println("Philosopher " + number + " " + message );

}

@Override
public void run() {
    if(keepGoing == true)
    {
        try
        {


            print("is hungry");
            print( "checks if forks are free");
            if(right.isFree() == true && left.isFree() == true && hasBothForks == false)
            {
                print("is grabbing forks");
                right.takeFork();
                left.takeFork();
                hasBothForks = true;
            } // end if
            else if(hasBothForks == true)
            {
                print("is eating");
                Thread.sleep(2000);
                print("is putting down left fork");
                left.returnFork();
                print("is putting down right fork");
                right.returnFork();
                print("is finished eating");
                hasBothForks = false;
            } // end if
            else if(right.isFree() == false && left.isFree() == false && hasBothForks == false)
                {
                    print("is thinking");
                    Thread.sleep(2000);
                } // end if             

        } // end try
        catch (InterruptedException e) {

                    print(" is interrupted");

        } // end catch
    } // end if


} // end run

餐桌:

private static int num = 5;
private static Forks right = null;
private static Forks left = null;
private static Forks[] forks = new Forks[num];
private static philosophers[] philosophers = new philosophers[num];

public static void main(String args[])
{
    for (int i = 0; i < num ; i++)
    {
        forks[i] = new Forks();
    }
        for (int i = 0; i < num; i++)
        {
            if (i > 0)
            {
                left = forks[i - 1];
                right = forks[i];
            } // end if
            else if ( i == 0)
            {
                left = forks[num-1];
                right = forks[i];
            } // end if

            philosophers[i] = new philosophers(i, right, left, true);

            Thread thread = new Thread(philosophers[i]);
            thread.start();

        } // end for

        System.out.print("\n");
}
4

2 回答 2

2

我发布了这个答案,因为我无法发表评论。

最初的问题是没有线程同步。由于竞争条件,所有哲学家都有可能获得两个分叉。

if(right.isFree() == true && left.isFree() == true && hasBothForks == false)
{
    print("is grabbing forks");
    right.takeFork();
    left.takeFork();
    hasBothForks = true;
}

如果它按此顺序发生:

P1: right.isFree() == true, left.isFree() == true, hasBothForks == false - thread is slept by the scheduler
P2: right.isFree() == true, left.isFree() == true, hasBothForks == false - thread is slept by the scheduler
P3: right.isFree() == true, left.isFree() == true, hasBothForks == false - thread is slept by the scheduler
P4: right.isFree() == true, left.isFree() == true, hasBothForks == false - thread is slept by the scheduler
P5: right.isFree() == true, left.isFree() == true, hasBothForks == false - thread is slept by the scheduler

P1: right.takeFork(), left.takeFork() - thread is slept by the scheduler
P2: right.takeFork(), left.takeFork() - thread is slept by the scheduler
P3: right.takeFork(), left.takeFork() - thread is slept by the scheduler
P4: right.takeFork(), left.takeFork() - thread is slept by the scheduler
P5: right.takeFork(), left.takeFork() - thread is slept by the scheduler

编辑:

解决这个线程问题的方法有两个。

首先,fork 实际上是一个线程安全的对象,称为MutexSemaphore。这意味着每个分叉只有 1 个令牌可用,其他请求此分叉的人必须等到它可用。

其次,您需要一种方法让哲学家不要先选择左叉,或者先选择右叉,因为这会导致饥饿。相反,您需要提出一个解决方案,例如让奇数哲学家左撇子(先抓住左叉子)和偶数哲学家右撇子(先抓住右叉子)。

解决了这两个问题后,您应该始终至少有 1 位哲学家能够吃东西,一旦他吃完,就会释放两个叉子(读取信号量)并允许其他哲学家获得叉子。

编辑2:

我建议的解决方案的一个很好的深入解释是:http ://www.cs.mtu.edu/~shene/NSF-3/e-Book/MUTEX/TM-example-left-right.html

于 2013-05-07T00:16:22.540 回答
0

将哲学家的方法中的更改if为 a后,尝试更新take 和 return 的函数,如下所示:whilerunForks

public synchronized void returnFork() throws InterruptedException
{
    available = true;
    this.notifyAll();
}

public synchronized void takeFork() throws InterruptedException
{
    while(!available){
      this.wait();
    }
    available = false;
}

然后,我对哲学家的方法进行了一些调整,run如下所示:

      if (!hasBothForks){
        print("is hungry");
        print( "checks if forks are free");            
      }

      if(right.isFree() == true && left.isFree() == true && hasBothForks == false)
      {
          print("is grabbing forks");
          right.takeFork();
          left.takeFork();
          hasBothForks = true;
      } // end if
      else if(hasBothForks == true)
      {
          print("is eating");
          Thread.sleep(2000);
          print("is putting down left fork");
          left.returnFork();
          print("is putting down right fork");
          right.returnFork();
          print("is finished eating");
          hasBothForks = false;
      } // end if
      else if((right.isFree() == false || left.isFree() == false) && hasBothForks == false)
          {
              print("is thinking");
              Thread.sleep(2000);
          } // end if 

通过这两组更改,我看到输出流好多了。仍然不确定它是否正是您想要的。

于 2013-05-07T00:23:16.717 回答