用餐哲学家,Java和监视器:IllegalMonitorStateException

时间:2014-03-19 19:14:56

标签: java multithreading concurrency

对于披露,这是关于经典餐饮哲学家困境的作业问题。

现在,当一个Thread被告知wait()因为其中一个筷子已经有一个wait()监视器时,会给出一个IllegalMonitorStateException。

Monitor类实例化一次,以哲学家的数量作为参数。监视器类如下所示:

public class Monitor 
{
        int iPhilosophers = DiningPhilosophers.DEFAULT_NUMBER_OF_PHILOSOPHERS;
        // monitors for chopsticks maybe use condition??
        public final Object[] sticks = new Object[iPhilosophers];

        // Store philosopher states in monitor. 
        public enum State {THINKING, HUNGRY, EATING, TALKING};
        public volatile State[] states = new State[iPhilosophers];
        public int[] positions = new int[iPhilosophers];


    public Monitor(int piNumberOfPhilosophers)
    {
        for (int i=0; i<piNumberOfPhilosophers; i++) {
            System.out.println("Philosopher " + (i+1) + " is " + this.states[i]);
            this.sticks[i] = new Object();

        }
    }

    /**
     * Grants request (returns) to eat when both chopsticks/forks are available.
     * Else forces the philosopher to wait()
     */
    public synchronized void pickUp(final int piTID)
    {
        int posn = piTID - 1; // due to piTIDs starting at 1, but stick positions @ 0
        this.states[posn] = State.HUNGRY;
        System.out.println("Hungry Philosopher "+ piTID + " is trying to pickup sticks");

        test(posn);
        System.out.println("Philosopher " + piTID +" is state " + this.states[posn]);
        if (this.states[posn] != State.EATING)
            try {
                System.out.println("Hungry Philosopher "+ piTID + " was told to work on his table manners and wait!");
                this.sticks[posn].wait();
//              synchronized (this.sticks[posn]){
//                  this.sticks[posn].wait();
//              }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    }
        /**
     * Test the chopsticks on the left and right of the philosopher
     * Give philosopher's position
     */
    public void test(int i){
        System.out.println("Entered test function with posn : " + i);
        System.out.println("left "+this.states[(i+iPhilosophers-1) % iPhilosophers]);
        System.out.println("right "+this.states[(i+1) % iPhilosophers]);
        System.out.println("currently " + this.states[i]);

        // Check if philosophers on left and right are not eating
        if ( (this.states[(i+iPhilosophers-1) % iPhilosophers] != State.EATING) &&
                (this.states[(i+1) % iPhilosophers] != State.EATING) &&
                (this.states[i] == State.HUNGRY) ) {
            // set this state to eating, and signal the chopstick

            this.states[i] = State.EATING;
            System.out.println("Set position " + i + " to " + this.states[i]);
            synchronized (this.sticks[i]) {
                this.sticks[i].notifyAll();
                System.out.println(i + " posn notified all");
            }
        }
    }

    /**
     * When a given philosopher's done eating, they put the chopstiks/forks down
     * and let others know they are available.
     */
    public synchronized void putDown(final int piTID)
    {
            System.out.println("entered putdown");
            int posn = piTID - 1; // due to piTIDs starting at 1
            this.states[posn] = State.THINKING;
            test((posn+iPhilosophers-1) % iPhilosophers);
            test((posn+1) % iPhilosophers);
            System.out.println("Philosopher " + piTID + " is back to " + this.states[posn]);
        }
}

生成的部分输出:

Philosopher 4 is state HUNGRY
Hungry Philosopher 4 was told to work on his table manners and wait!
Hungry Philosopher 2 is trying to pickup sticks
Entered test function with posn : 1
left EATING
right EATING
currently HUNGRY
Philosopher 2 is state HUNGRY
Hungry Philosopher 2 was told to work on his table manners and wait!
Exception in thread "Thread-3" Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:503)
    at Monitor.pickUp(Monitor.java:61)
    at Philosopher.run(Philosopher.java:87)
java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:503)
    at Monitor.pickUp(Monitor.java:61)
    at Philosopher.run(Philosopher.java:87)

我尝试了一些不同的东西,但无法弄清楚如果另一个已经在等待的话,如何允许任何哲学家等待()。我需要使用条件吗?

请注意,这类似于基于相同O / S手册的问题Dining Philosophers monitor approach in Java: no interleaved thread execution,但没有帮助我解决此问题。

2 个答案:

答案 0 :(得分:1)

你有

        System.out.println("Hungry Philosopher "+ piTID + " was told to work on his table manners and wait!");
        this.sticks[posn].wait();

您需要在synchronized对象上this.sticks[posn](也称为自己的监视器)才能调用该对象上的wait()notify方法。

稍后在您的代码中正确使用

synchronized (this.sticks[i]) {
            this.sticks[i].notifyAll();
            System.out.println(i + " posn notified all");
        }

您正在this.sticks[i]和正在调用notifyAll()同步。对wait()案例也一样。

答案 1 :(得分:0)

结束更改所有内容以使用条件和锁定。不是解决这个问题的最佳方法,但是我们可以指定任务。