2009-03-19 18 views
31

la siguiente función se ejecuta en su propio hilo:Enhebrado en Java: cómo bloquear un objeto?

private void doSendData() 
{ 
    try { 

      //writeToFile(); // just a temporary location of a call 
      InetAddress serverAddr = InetAddress.getByName(serverAddress); 
      serverAddr.wait(60000); 
      //Log.d("TCP", "C: Connecting..."); 
      Socket socket = new Socket(serverAddr, portNumber); 
      socket.setSoTimeout(3000); 

       try { 
       //Log.d("TCP", "C: Sending: '" + message + "'"); 
       PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true); 
       String message = packData(); 
       out.println(message); 
       Log.d("TCP", "C: Sent."); 
       Log.d("TCP", "C: Done."); 
       connectionAvailable = true; 

      } catch(Exception e) { 
       Log.e("TCP", "S: Error", e); 
       connectionAvailable = false; 

       } finally { 
        socket.close(); 
        announceNetworkAvailability(connectionAvailable); 
       } 

     } catch (Exception e) { 
       Log.e("TCP", "C: Error", e); 
       announceNetworkAvailability(connectionAvailable); 
     } 
} 

Cuando la ejecución alcanza la línea serverAddr.wait(60000) lanza una excepción:

java.lang.IllegalMonitorStateException: object not locked by thread before wait() 

¿Alguien sabe cómo bloquear un objeto o una función en Para evitar la concurrencia? He intentado añadir un objeto de bloqueo:

private final Lock lock = new ReentrantLock(); 

y la línea

boolean locked = lock.tryLock(); 

al comienzo de la función, pero no funcionó.

+0

¿Qué quieres hacer? El WAIT no tiene ningún sentido ... – ReneS

Respuesta

64

Con el fin de llamar a wait() en un objeto, usted tiene que mantener el bloqueo sincronizado en ese objeto (aunque el bloqueo se libera realmente mientras que el flujo espera):

synchronized (serverAddr) { 
    serverAddr.wait(); 
} 

tengo que admitir que qué usted está queriendo hacer esto me desconcierta en este caso ...

+0

Lo siento, solo para ser claro: entiendo por qué tienes que adquirir el candado del objeto antes de esperarlo. ¡Lo que no entiendo es la * lógica * de lo que el cartel original realmente está tratando de hacer ...! –

+1

Ah, entonces mi comentario está redactado :) –

+1

+1 por "la cerradura se está liberando mientras el hilo está esperando", me ayudó a solucionar otro problema y no estaba al tanto de eso (sí, soy nuevo en Java) – spirytus

1

Para evitar este mensaje de error, utilice la palabra clave sincronizada:

synchronized(serverAddr){ 
    serverAddr.wait(60000); 
} 
11

Siempre me estremezco cuando veo este tipo de código. Hazte un favor y eche un vistazo al paquete java.util.concurrent.

+0

echa un vistazo a mi pregunta también. http://stackoverflow.com/q/31966790/4260932 –

1

Lo anterior es correcto. Puede usar un bloque de código sincronizado. O puede crear lo que ellos llaman un mutex. Un mutex puede ser cualquier objeto. Muchas personas simplemente usan Object como un mutex. Entonces puedes bloquear el mutex. Cualquier subproceso que desee obtener acceso debe esperar al hilo que contiene el mutex para liberarlo.

También hubo una sugerencia de Apocalisp. También recomendaría que miraras el paquete java.util.concurrent.

21

Quizás el método que está buscando es Thread.sleep(long)? Este método hará que espere (como detener la ejecución del subproceso) durante el tiempo especificado en milisegundos antes de reanudar.

object.wait(long) (que es lo que está utilizando) hace algo completamente diferente. Espera a que otro objeto de otro hilo lo notifique (es decir, le envíe una especie de mensaje de activación) y esperará como máximo el número especificado de milisegundos. Dado el código que publicaste, dudo mucho que esto sea lo que realmente quieres.

Si Thread.sleep() no es lo que desea, entonces debe utilizar el bloque sincronizado como se menciona en los otros carteles.

+0

por favor eche un vistazo a mi pregunta http://stackoverflow.com/q/31966790/4260932 –

0

En general, cuando tiene un programa de subprocesos múltiples en Java, necesita bloquear la variable compartida mediante sincronización (palabra clave) y, en cualquier momento, solo un subproceso puede acceder a la memoria compartida.

0

El siguiente código debería funcionar.

 private final ReentrantLock lock = new ReentrantLock(); 

    lock.lock(); // block until condition holds 
    try { 
     serverAddr.wait(60000); 
    } finally { 
     lock.unlock() 
    } 
    } 

se refieren a esta documentación page para más detalles.

public void lock() 

adquiere el bloqueo.

Adquiere el candado si no lo retiene otro hilo y lo devuelve inmediatamente, estableciendo el conteo de espera de bloqueo en uno.

Si el hilo actual ya mantiene el bloqueo, el conteo de espera se incrementa en uno y el método regresa inmediatamente.

Si el bloqueo está en manos de otro hilo, entonces el hilo de corriente llega a ser desactivado para fines de programación hilo y permanece latente hasta que el bloqueo se ha adquirido, en cuyo momento el recuento de retención de bloqueo se establece en uno

Consulte este sE trata de conocer las ventajas de lock sobre synchronization:

Synchronization vs Lock

Cuestiones relacionadas