【问题标题】:Dining Philosophers, Java and Monitors: IllegalMonitorStateException餐饮哲学家、Java 和监视器:IllegalMonitorStateException
【发布时间】:2014-03-19 19:14:56
【问题描述】:

为了披露,这是一个关于经典餐饮哲学家困境的家庭作业问题。

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

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)

我尝试了一些不同的方法,但不知道如何让任何哲学家等待(),如果另一个人已经在等待。我需要使用条件吗?

请注意,这类似于问题Dining Philosophers monitor approach in Java: no interleaved thread execution,它基于同一本操作系统书籍,但并没有帮助我解决这个问题。

【问题讨论】:

  • 阅读wait()的javadoc。
  • +1 用于深思熟虑的问题和背景研究。寻求帮助是可以的,只要你不要求我们为你做作业(你不是,所以,很好)。
  • 如果你有一把巨大的锁在一切之上,这并不是真正的哲学家进餐问题。此外,对易失性数组的写入也不是易失性的,但是随着所有锁定的进行,我认为无论如何都没有必要。

标签: java multithreading concurrency


【解决方案1】:

给你

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

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

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

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

您正在与this.sticks[i] 和调用notifyAll() 同步。对 wait() 案例执行相同操作。

【讨论】:

  • 感谢您的快速回复。这样做似乎已经摆脱了 IllegalStateException 错误,但是现在出现了死锁。吃完饭后,哲学家不能 putDown() 他的筷子。我想这可能是因为另一位哲学家可能正试图放下自己的筷子,尽管我不确定。
【解决方案2】:

最终将所有内容更改为使用条件和锁定。不是解决这个问题的最佳方法,但作业表明我们可以。

【讨论】:

    猜你喜欢
    • 2016-03-04
    • 2013-05-10
    • 1970-01-01
    • 2013-01-28
    • 1970-01-01
    • 2016-06-17
    • 2013-05-12
    • 2019-02-07
    • 2010-10-26
    相关资源
    最近更新 更多