Pregunta

Estoy usando múltiples hilos en mi aplicación. Básicamente, tengo un cuadro combinado y al seleccionar la bandeja de entrada, los currículums P1 y P2 se suspenden y al seleccionar el envío, P2 comienza y se detiene P1. A continuación se muestra el código (estoy seguro de que no es perfecto)

public void modifyText(ModifyEvent e) {
                if (combo.getText().equals("Inbox"))
                {
                    synchronized(p2) 
                    {
                        p2.cont = false;
                    }
                    table.removeAll();
                    synchronized(p1)
                    {
                        p1.cont = true;
                        p1.notify();
                    }
                }


                else if (combo.getText().equals("Sent"))
                {
                    synchronized(p2) 
                    {
                        p1.cont = false;
                    }
                    table.removeAll();
                    synchronized(p1)
                    {
                        p2.cont = true;
                        p2.notify();
                    }
                }
            }
        });

Y para P1 y P2 tengo esto dentro de sus bucles While:

synchronized (this) {
            while (cont == false)
                try {
                    wait();
                } catch (Exception e) {
                }
        } 

... Como está funcionando ahora (soy un principiante para los hilos). Al presionar enviado en el cuadro combinado, obtengo una ilegaltatemonitorException. ¿Alguien podría ayudarme a resolver el problema por favor?

Gracias y saludos, krt_malta

¿Fue útil?

Solución

El problema está aquí:

synchronized(p1)
{
    p2.cont = true;
    p2.notify();
}

Tú lo estás haciendo p2.notify() Cuando no tienes un bloqueo p2 (Debe mantener el monitor para llamar a él). Cambio synchronized(p1) a synchronized(p2). Además, también debe revertir la otra cláusula sincronizada que también es defectuosa. Entonces, como ejemplo:

synchronized(p1) 
{
    p1.cont = false;
    // p1.notify(); <- do you need this here?
}
table.removeAll();
synchronized(p2)
{
    p2.cont = true;
    p2.notify();
}

Además, su otro código también está un poco incorrecto, es muy mala práctica bloquear dentro de un bucle completo, hacerlo un poco más atómico.

while (!cont) {
    synchronized (this) {
       try {
           wait();
       } catch (Exception e) {
       }
    }
}

Optimización adicional, evite synchronised si es posible:

if (p1.cont) {
   synchronized(p1) 
   {
       p1.cont = false;
       // p1.notify(); <- do you need this here?
   }
}
table.removeAll();

if (!p2.cont) {
   synchronized(p2)
   {
       p2.cont = true;
       p2.notify();
   }
}

Hacer el campo contenido volatile Aquí, y reflejen la otra parte de la declaración IF según corresponda.

EDITAR: Mirando hacia atrás en esto y luchar con un error de concurrencia que me enfrentaba recientemente, cualquiera que implemente este patrón podría enfrentar un problema con una espera infinita, si un objeto que está bloqueado y a medias está siendo mirada por el condicional de la misma manera bucle (esto se debe a que hay una brecha en la que el estado puede cambiar entre evaluar el condicional y la imposición de la declaración de espera). En este caso, coloque el bloque sincronizado en el fuera de del bucle.

Otros consejos

En este código

                synchronized(p1)
                {
                    p2.cont = true;
                    p2.notify();
                }

Te estás sincronizando p1 Pero llamando notify() en p2, que conduce a la excepción.

No puede esperar en el hilo de despacho de eventos AWT o de lo contrario que mantendrá toda su aplicación. Leer acerca de http://en.wikipedia.org/wiki/event_dispatching_thread

Además, no debe usar hilos sin procesar a menos que realmente sepa lo que está haciendo. Verificar http://java.sun.com/javase/6/docs/api/java/util/concurrent/package-summary.html y leer Ejecutores

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top