2011-03-14 22 views
7

Supongamos que estoy ejecutando un bloque de código synchronized dentro de un hilo y dentro del bloque synchronized llamo un método que genera otro hilo para procesar un bloque de código sincronizado que requiere el mismo bloqueo que el primer método . Así que en pseudo código Java:Hilos de Java y bloques sincronizados

public void someMethod() { 
    synchronized(lock_obj) { 
    // a whole bunch of stuff... 

    // this is the last statement in the block 
    (new Thread(someOtherMethod())).start(); 
    } 
    // some more code that doesn't require a lock 
} 

public void someOtherMethod() { 
    // some setup code that doesn't require a lock 

    // return the stuff we want to run in another thread 
    // that does require a lock 
    return new Runnable() { 
    @Override 
    public void run() { 
     synchronized(lock_obj) { 
     // some more code 
     } 
    } 
    }; 
} 

No tengo idea de cómo darle sentido a ese código. ¿Es lo que he escrito incluso legal? Sintácticamente no veo ningún problema, pero no estoy seguro de cómo razonar a través de un código como ese. Entonces, cuando ejecuto someOtherMethod() para crear una instancia de Runnable, ¿en qué tipo de ámbito se ejecuta el código anterior a la instrucción return? ¿Se ejecuta como parte del primer bloque sincronizado? Supongamos que hay otros subprocesos que también funcionan y que pueden requerir el bloqueo en lock_obj.

Respuesta

8

Aún mantiene presionado el candado durante la creación del hilo ejecutable y el hilo, pero después de llamar al inicio y antes de que el hilo realmente capte, está renunciando al bloqueo. El nuevo hilo tendrá que competir por el bloqueo con otros hilos.

5

No hay nada de malo en este código. Antes de la declaración de devolución en someOtherMethod(), el código se está ejecutando en el bloque sincronizado de someMethod(). Después de que se inicia el nuevo subproceso, se bloqueará en la instrucción synchronized dentro del método run() hasta que obtenga un bloqueo en lock_obj (como muy pronto, siempre que someMethod() salga de su bloque sincronizado).

+0

simplemente agregando algo que podría perderse: el bloque sincronizado en someMethod() se cierra tan pronto como se invoca start() y el nuevo subproceso se ejecuta de forma paralela. Esto parece haber sido lo que causó la confusión del OP. –

+0

@AbrahamPhilip - No lo pondría de esa manera. El bloque sincronizado no se cierra cuando se llama a 'start()'. (Sale muy poco tiempo después, porque la llamada a 'start()' pasa a ser la última instrucción en el bloque sincronizado). Más bien, al llamar 'start()' inicia la ejecución de otro hilo (que comienza sin monitores) celebrada), ejecutando el código en el 'Runnable' devuelto por' someOtherMethod() '. Ese otro hilo necesita esperar a que el bloque en 'someMethod()' salga antes de que pueda ingresar su propio bloque sincronizado. –

+0

lo siento, tienes toda la razón. Permítanme reformular, "justo después" se llama start(). Solo quería resaltar eso porque el OP se preguntaba si el ejecutable del segundo subproceso se estaba ejecutando dentro del primer bloque sincronizado (como una respuesta aquí afirmó erróneamente http://stackoverflow.com/a/5295252/3000919). Creo que su comentario lo explica muy bien, gracias :) –

-2

Si someMétodo() se invoca primero, es el ejemplo clásico de un interbloqueo.

¿Es lo que he escrito incluso legal?
---- Sí, es perfectamente legal sintácticamente.

Entonces, cuando ejecuto someOtherMethod() para crear una instancia de Runnable, ¿en qué tipo de ámbito se ejecuta el código anterior a la instrucción return? ---- Si someOtherMethod() se invoca desde algún método(), entonces está en el alcance del bloque sincronizado del método someMethod().

+1

¿Por qué es un punto muerto? Thread.start regresa inmediatamente y en ese momento se libera el bloqueo de lock_obj, en cuyo momento Runnable que se devuelve retoma el bloqueo o espera otro hilo para liberarlo. – davidk01

+1

Esté de acuerdo con @davidk01 en que este no es un punto muerto. Y ciertamente no es el ejemplo "clásico" de uno si lo fue. Solo para obtener más información, incluso sin el inicio del subproceso, llamar a un método en java que está sincronizado en el mismo bloqueo que ya tiene un hilo no se bloqueará, ya que el que llama ya posee el bloqueo. – Sogger