Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 餐饮哲学家的任务。将我的概念转化为代码_Java_Multithreading_Illegalmonitorstateexcep - Fatal编程技术网

Java 餐饮哲学家的任务。将我的概念转化为代码

Java 餐饮哲学家的任务。将我的概念转化为代码,java,multithreading,illegalmonitorstateexcep,Java,Multithreading,Illegalmonitorstateexcep,我对Java线程相当陌生。尝试使用Java的同步概念实现死锁机制。这里面有一些问题。我想知道我应该如何改进我的代码我的目标是避免僵局 package threading; import java.util.logging.Level; import java.util.logging.Logger; public class DiningPhilospherProblem { public static void main(String[] args) { Chops

我对Java线程相当陌生。尝试使用Java的同步概念实现死锁机制。这里面有一些问题。我想知道我应该如何改进我的代码我的目标是避免僵局

package threading;

import java.util.logging.Level;
import java.util.logging.Logger;


public class DiningPhilospherProblem {

  public static void main(String[] args)
  {
      Chopstick cs[] = new Chopstick [5];
      for(int i=0;i<5;i++)
      {
          cs[i] = new Chopstick();
      }


      new Thread(new Philospher("One", cs[4],cs[0]) ).start();
      new Thread(new Philospher("Two", cs[0],cs[1]) ).start();
      new Thread(new Philospher("Three", cs[1],cs[2]) ).start();
      new Thread(new Philospher("Four", cs[2],cs[3]) ).start();
      new Thread(new Philospher("Five", cs[3],cs[4]) ).start();
  }
}

class Philospher implements Runnable
{
    private static final int EATING_TIME = 8000;
    private static final int THINKING_TIME  = 10000;


    public enum State {
        EATING, THINKING, WAITING
    }

    Chopstick left, right;
    String name;
    State state;
    public Philospher(String name, Chopstick left,Chopstick right)
    {
        System.out.println(" Philospher "  + name + " is ready");
        this.name = name;
        this.left =left;
        this.right = right;
    }
    public void run()
    {
       for(int i =0; i< 10;i++){

                eat();

        }

        System.out.println("Succesfully finished: " +name);
    }
    public void eat()  // EDITED THIS FUNCTION
    {
        synchronized(left){
        try{


                while(right.isBeingUsed()){
                    System.out.println("Philospher " + name + " :  is waiting");
                    setPhilosopherState(Philospher.State.WAITING);
                    left.wait();
                }

                synchronized(right)
                {
                    left.setChopStickUsed(true);
                    right.setChopStickUsed(true);

                    System.out.println("Philospher " + name + " :  is eaitng");
                    setPhilosopherState(Philospher.State.EATING);

                    Thread.sleep(EATING_TIME);
                }
            }

        catch(InterruptedException e){}
        finally
        {
            left.setChopStickUsed(false);
            right.setChopStickUsed(false);
            left.notify();

        }
        }
        think();

    }

    public void think()
    {
        System.out.println("Philospher " + name + " :  is thinking");
        try 
        {
            setPhilosopherState(State.THINKING);
            Thread.sleep(THINKING_TIME);
        } 
        catch (InterruptedException ex) {
            Logger.getLogger(Philospher.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
     private void setPhilosopherState(State state){
        this.state = state;

        System.out.println("Setting state :  "+ state +", "+ name+";");
    }
}

class Chopstick
{
    boolean state_chopstick;

    public synchronized void  setChopStickUsed(boolean value)
    {
        state_chopstick = value;

    }
    public synchronized boolean isBeingUsed ()
    {
        return state_chopstick;
    }
}
包线程;
导入java.util.logging.Level;
导入java.util.logging.Logger;
公共类餐饮业问题{
公共静态void main(字符串[]args)
{
筷子cs[]=新筷子[5];

对于(int i=0;i您将获得一个
非法监视异常
,因为您在
eat
中等待
,而没有持有对象上的锁(
)。您应该查看

此外,您也不会调用
notify
notifyAll
,因此您将永远等待


你可能想
思考
而不是
等待

除了assylias对你直接问题的回答之外,这里有一些关于改进逻辑的建议:

在检查
left.isBeingUsed()
left.setChomptickUsed(true);
其他人可能已经抓住了筷子(这称为检查时间与使用时间的问题)。为确保不会发生这种情况,您需要使用适当的机制,只允许一位哲学家访问筷子对象,并以原子方式执行检查+抓取,例如,将eat的逻辑替换为

boolean isEating = false;
if (left.grab()) {
  if (right grab) {
    // managed to grab both chopsticks
    isEating = true;
  } else {
    // only grabbed the left one
    left.release();
  }
} else {
  // could not grab the left one
}

if (isEating) {
  // TODO: chew, swallow
  left.release();
  right.release();
} else {
  // contemplate the cruelty of life
  think();
}
其中,
筷子
有以下方法:

public synchronized boolean grab()
{
  if (state_chopstick) {
    // already in use
    return false;
  }
  _state_chopstick = true;
  return true; // managed to grab it
}

public synchronized void release()
{
  state_chopstick = false;
}
想法是
grab()
检查筷子是否在使用中,如果不在使用中就抓住它(这避免了检查时间/使用时间问题)


注意:上述实现可能会导致live lock,即所有哲学家同时抓取左边的筷子,然后找到正在使用的右边的筷子,松开左边的筷子,思考并重复;这样就不会吃东西。要解决这个问题,您可以动态地(例如随机地)决定首先抓取哪个叉子

您有什么问题?“这里面有一些问题”你的意思是除了不合逻辑和不一致的缩进之外?什么?顺便说一句-你有问题吗?无法知道我的理解是否正确!!!它抛出非法监视异常..想知道我哪里出错了
非法监视异常
复制/粘贴异常输出。你修改的
eat()
仍然会产生不良行为:1)您对
right.isBeingUsed()
的检查与
synchronized(right)
是分开的,因此另一个线程可能会同时抓住该分叉;2)您在输入
synchronized(left)
之前不检查左分叉是否正在使用,并假设它不是;3)您的最终是(再次)与同步块分开,另一个线程可以[…参见上文…]