2015-04-08 12 views
0

Я новичок в мониторах и переменных условий. Я использую блокировку и переменные условия на моем мониторе.java.lang.IllegalMonitorStateException в классе мониторов обеденных философов

public class Monitor 
{ 
    private final int piNumberOfPhilosophers; 
    private PhilosopherCard[] self; 
    private Integer[] names; 
    private int invited = 0; 
    static Lock lock = new ReentrantLock(); 
    private Condition[] status; // = lock.newCondition(); 
    private String[] state; 
    /** 
    * Constructor 
    */ 
    public Monitor(int piNumberOfPhilosophers) 
    {  this.piNumberOfPhilosophers = piNumberOfPhilosophers;   

     self = new PhilosopherCard[this.piNumberOfPhilosophers]; 
     names = new Integer[this.piNumberOfPhilosophers]; 
     status = new Condition [this.piNumberOfPhilosophers]; 
     state = new String [this.piNumberOfPhilosophers]; 
     //Arrays.asList(state).indexOf(4);  
     } 

    public void invitePhilosopher (int id){ 

     names[invited] = id; 
     System.out.println(invited); 
     PhilosopherCard philosopher = new PhilosopherCard("thinking"); 
     self[invited] = philosopher; 
     status[invited] =lock.newCondition(); 
     state[invited] = "thinking"; 
     invited++; 
     }   
    /** 
    * check other philosophers (<_<) - > (0_o) -> (>_>) 
    */ 

    private void test (int index){ 
     lock.lock(); 

     int left = index-1; 
     int right = index +1; 
     if(index==0){ 
      left=piNumberOfPhilosophers-1; 
     } 
     if(index == piNumberOfPhilosophers-1){ 
      right = 0; 
     } 
     if((state[left]!="eating")&(state[right]!="eating")){ 
      state[index]="eating"; 
      status[index].signal(); 
      } 
     lock.unlock(); 

    } 


    public void pickUp(final int piTID) throws InterruptedException 
    {   
     int index = Arrays.asList(names).indexOf(piTID);  
     state[index]="hungry"; 
     test(index); 
     if(!state[index].equals("eating")){  
       status[index].wait(); 
     } 
    } 

    /** 
    * When a given philosopher's done eating, they put the chopstiks/forks down 
    * and let others know they are available. 
    */ 
    public void putDown(final int piTID) 
    { 
     int index = Arrays.asList(names).indexOf(piTID); 
     self[index].setState("thinking"); 

     int left = index-1; 
     int right = index +1; 
     if(index==0){ 
      left=piNumberOfPhilosophers-1; 
     } 
     if(index == piNumberOfPhilosophers-1){ 
      right = 0; 
     } 
     test(left); 
     test(right); 

     // ... 
    } 


} 

In putdown мы можем самостоятельно [index] .signal, чтобы просыпаться мониторы. Но это не так важно. И в случае сбоя отслеживания наблюдается исключение монитора, когда мы используем wait on condition variable. Зачем? Потому что все они используют 1 замок? Все следы

Exception in thread "Thread-1" Exception in thread "Thread-3" java.lang.IllegalMonitorStateException 
    at java.lang.Object.wait(Native Method) 
    at java.lang.Object.wait(Unknown Source) 
    at Monitor.pickUp(Monitor.java:75) 
    at Philosopher.run(Philosopher.java:95) 
java.lang.IllegalMonitorStateException 
    at java.lang.Object.wait(Native Method) 
    at java.lang.Object.wait(Unknown Source) 
    at Monitor.pickUp(Monitor.java:75) 
    at Philosopher.run(Philosopher.java:95) 

Я обновил код и удалить дополнительный класс, так что все в одном классе, может быть, сейчас это более понятно, где может быть, что ошибка

+1

, пожалуйста, дайте полный стек исключения, это, как правило, хороший первый шаг в отладке – flup

+1

Не смешивайте синхронизацию и 'java.util.concurrent.' Таким образом безумие лежит. – EJP

+0

да, но это все равно работает – Ophelia

ответ

2

Там целый ряд вещей, которые вы делаете неправильно.

  1. Вы synchronizing на this и не обрекать на PhilosopherCard.lock. Запирание, я имею в виду PhilosopherCard.lock.lock();
  2. Вы используете wait вместо await.

Update для получения дополнительной информации

Если вы посмотрите на этот код твоего и удалить synchronized код не подведет.

private void test (int index){ 
     PhilosopherCard.lock.lock(); 
     int left = index-1; 
     int right = index +1; 
     if(index==0){ 
      left=piNumberOfPhilosophers-1; 
     } 
     if(index == piNumberOfPhilosophers-1){ 
      right = 0; 
     } 
     if((state[left]!="eating")&(state[right]!="eating")){ 
      state[index]="eating"; 
      status[index].signal();; 
      } 
     PhilosopherCard.lock.unlock(); 
    } 

Где вы signal он похож на await, но не синхронизированы, почему он не будет бросать IMSE? Это потому, что вы держите замок PhilosopherCard.lock. Если вы удалите эти два замка, вы получите IMSE.

Вы столкнулись с этой проблемой в pickUp. Я удаляю synchronized из метода все вместе. Зачем? Потому что вы смешиваете синхронизацию. Если вы хотите выполнить синхронизацию с synchronized, это нормально, но если вы выполняете синхронизацию с java.util.concurrent.Lock, вы не можете использовать synchronized.

synchronized ключевое слово может позволить вам использовать wait, notify и notifyAll на объекте.

j.u.c.Lock и j.u.c.Condition позволяют использовать await, signal, signalAll. Поэтому мое предложение либо используется только Lock/Condition, либо synchronized. Не оба.

+0

nah, ждет такая же ошибка – Ophelia

+1

Если вы делаете (1) перед сигнализацией, она будет работать правильно. –

+0

Он прав, условия требуют ожидания(). Но чтобы исключить IllegalMonitorStateException, вам нужно сначала синхронизировать с соответствующим объектом. – flup