/ / ¿Por qué múltiples hilos pueden acceder a un bloque sincronizado? [duplicado]: java, multihilo, sincronizado, ilegalmonitorstateexcep

¿Por qué múltiples hilos pueden acceder a un bloque sincronizado? [duplicado] - java, multihilo, sincronizado, illegalmonitorstateexcep

Mientras se ejecuta esto estoy "recibiendo IllegalMonitorStateException porque incluso el hilo está intentando notificar cuando no tiene bloqueo en el objeto isEven. ¿Por qué está pasando esto? Un subproceso solo debe poder ir dentro del bloque sincronizado si tiene bloqueo en el objeto.

public class NumPrinter implements Runnable{

public static Boolean isEven = true;
private boolean isEvenThread;
private int i;

public void run() {
while(i < 100){
synchronized(isEven){
boolean notPrinting = (isEven ^ isEvenThread);
System.out.println(notPrinting);
if(notPrinting) {
try {
isEven.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(i + ",");
i = i+2;
isEven = !isEven;
isEven.notifyAll();
}
}
}

public NumPrinter(boolean isEvenThread) {

this.isEvenThread = isEvenThread;
if(isEvenThread)
i = 0;
else
i = 1;
}
}

public class MultiThreading {

public static void main(String[] args) {

Thread oddt = new Thread(new NumPrinter(false), "Odd");
Thread event = new Thread(new NumPrinter(true), "Even");

event.start();
oddt.start();


}
}

Respuestas

2 para la respuesta № 1

Es probable que necesite sincronizar / esperar / notificar en el objeto constante en su lugar. También declare isEven como volátil Por último, poner wait() Llame en el bucle, verificando la condición del bucle como documentación oficial. recomienda:

public class NumPrinter implements Runnable {
private static final Object monitor = new Object();
private static volatile boolean isEven = true;
private final boolean isEvenThread;
private int i;

@Override
public void run() {
while (i < 100) {
synchronized (monitor) {
while (isEven ^ isEvenThread) {
try {
monitor.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(i + ",");
i = i + 2;
isEven = !isEven;
monitor.notifyAll();
}
}
}
...
}

1 para la respuesta № 2

No soy un experto en Java, pero reescribes el token de sincronización aquí:

isEven =! isEven;

Puede que no sea el único problema que tenga, pero use al menos otro token de sincronización (que no se va a reescribir).