Monitores

Cyttorak
28 de Marzo del 2005
Hola.

Estoy implementando en java el problema de los filosofos que tienen que compartir los tenedores para poder comer.

Y al usar el notify me da la siguiente excepcion:
java.lang.IllegalMonitorStateException: current thread not owner

Este es el codigo de Mesa.java

public class Mesa {
private static Filosofo filosofos[];
public Mesa (int fs) {
filosofos=new Filosofo[fs];
Monitor m = new Monitor(fs);
for (int i=0;i<fs; i++) {
filosofos[i] = new Filosofo(m,i);
}
}

public static void main(String[] args) {
try {
Mesa mesa_de_filososfos;
mesa_de_filososfos = new Mesa(5);
for (int i=0;i<filosofos.length; i++) {
filosofos[i].start();
}
for (int i=0;i<filosofos.length; i++) {
filosofos[i].join();
}
} catch (InterruptedException e) {}
}
}

Y este el codigo de Filosofo.java

import java.lang.Thread;

public class Filosofo extends Thread {
private Monitor m;
private int id;
public Filosofo (Monitor mo, int ide) {
m=mo;
id=ide;
}
public Filosofo () {
}
public void setMonitor (Monitor mo, int ide) {
m=mo;
id=ide;
}
public final void run() {
try {
while (true) {
//Pensar
m.inicioComer(id);
//Comer
m.finComer(id);
}
} catch (InterruptedException e) {}
}
public static final void main (final String[] args) {
Thread p = new Thread(new Filosofo(),"mia");
p.start();
}
}

Y este es el codigo de Monitor.java

public class Monitor {
private int N;
private boolean comiendo[];
private boolean reserva[];
public Object varcond[];

public Monitor (int n) {
N=n;
comiendo = new boolean [n];
reserva = new boolean [n];
varcond = new Object [n];
for (int i=0; i<n; i++) {
comiendo[i]=false;
reserva[i]=false;
varcond[i]=new Object(); //Esto no se si sobra
}
}

public synchronized void inicioComer(int f) throws InterruptedException {
reserva[(f)%N]=true;
while ((comiendo[(f+N-1)%N]) ||
(comiendo[(f+1)%N]) ||
((reserva[(f+N-1)%N]) && ((comiendo[(f+N-2)%N]))))
{
varcond[f%N].wait();
}
System.out.println(f+" empieza a comer");
reserva[(f)%N]=false;
varcond[(f+1)%N].notify(); //Salta java.lang.IllegalMonitorStateException: current thread not owner
comiendo[(f)%N]=true;
}
public synchronized void finComer(int f) {
System.out.println(f+" acaba de comer");
comiendo[f]=false;
varcond[(f+1)%N].notify(); //Salta java.lang.IllegalMonitorStateException: current thread not owner
varcond[(f+N-1)%N].notify(); //Salta java.lang.IllegalMonitorStateException: current thread not owner
}
}

¿Alguien sabe como puedo hacer que funcione bien?

Si pongo simplemente wait() donde los wait y notifyAll donde los notify (en ambos casos llamando a los metodos del propio objeto monitor y no al de la variable de la posicion del array) parece que funciona, o al menos no da la excepcion pero se supone que eso es menos eficiente porque despierta en los notify a mas procesos de los que debiera.

Cyttorak
28 de Marzo del 2005
http://www.rafb.net/paste/results/qQLVuf54.html <- Lo mismo pero con colorines y tabulado para que se vea mejor el codigo