Pregunta

Me preguntaba si en Java obtendría algún comportamiento extraño si sincronizo dos veces en el mismo objeto.

El escenario es el siguiente

pulbic class SillyClassName {

    object moo;
    ...
    public void method1(){
        synchronized(moo)
        {
            ....
            method2();
            ....
        }
    }

    public void method2(){
        synchronized(moo)
        {
            doStuff();
        }
    }
}

Ambos métodos usan el objeto y se sincronizan en él. ¿Se detendrá el segundo método cuando sea llamado por el primer método porque está bloqueado?

No lo creo porque es el mismo hilo, pero no estoy seguro de ningún otro resultado extraño que pueda ocurrir.

¿Fue útil?

Solución

Reentrante

Los bloques sincronizados utilizan reentrantes , lo que significa que si el hilo ya contiene el bloqueo, puede volver a adquirirlo sin problemas. Por lo tanto, su código funcionará como espera.

Vea la parte inferior de la Tutorial de Java Bloqueos intrínsecos y sincronización .

Para citar a partir de 2015-01 ...

  

Sincronización de reentrada

     

Recuerde que un hilo no puede adquirir un bloqueo que pertenece a otro hilo. Pero un hilo puede adquirir un bloqueo que ya posee. Permitir que un subproceso obtenga el mismo bloqueo más de una vez habilita sincronización de reentrada . Esto describe una situación en la que el código sincronizado, directa o indirectamente, invoca un método que también contiene código sincronizado, y ambos conjuntos de código usan el mismo bloqueo. Sin la sincronización de reentrada, el código sincronizado tendría que tomar muchas precauciones adicionales para evitar que una secuencia se bloquee.

Otros consejos

Creo que tenemos que usar el bloqueo de reentrada para lo que estás tratando de hacer. Aquí hay un fragmento de http: //docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html .

  

¿Qué queremos decir con un bloqueo de reentrada? Simplemente hay un recuento de adquisiciones asociado con el bloqueo, y si un subproceso que mantiene el bloqueo lo adquiere nuevamente, el recuento de adquisiciones se incrementa y el bloqueo debe liberarse dos veces para liberar realmente el bloqueo. Esto es paralelo a la semántica de sincronizado; Si un subproceso entra en un bloque sincronizado protegido por un monitor que ya posee, el subproceso podrá continuar y el bloqueo no se liberará cuando el subproceso salga del segundo (o posterior) bloque sincronizado, pero solo se liberará cuando sale del primer bloque sincronizado, ingresa protegido por ese monitor.

Aunque no lo he probado, supongo que si quieres hacer lo que tienes arriba, tienes que usar un bloqueo de reingreso.

Java parece ser totalmente compatible con los bloqueos anidados en un objeto por el mismo hilo. Esto significa que si un subproceso tiene un bloqueo externo e interno en un objeto, y otro subproceso intenta bloquearlo en el mismo objeto, el segundo subproceso se suspenderá hasta que ambos hayan sido liberados por el primer hilo.

Mis pruebas se realizaron bajo Java 6 SE.

No hay problemas. En su ejemplo, (una vez que arregle su código para deshacerse de las advertencias de compilación que obtendrá;), la sincronización garantiza que los bloques en method1 y method2 no se ejecutarán simultáneamente.

Ese es el tipo de punto de sincronización. :)


Edit: Lo siento, faltamos partes de tu pregunta, pero Phill la respondió. Para resumir, un solo hilo no puede bloquearse por sí mismo.

En java, la palabra clave sincronizada en un método básicamente se sincroniza en el objeto actual, por lo que, de hecho, está haciendo lo que sugieres implícitamente.

No experimentará problemas con la sincronización en un objeto en un método y luego en el mismo objeto en otro método porque, como usted dice, el hilo actual ya tiene el bloqueo en ese objeto.

No, el segundo método no se detendrá si es llamado por el primero. No se producirán resultados imprevistos (excepto una ligera sobrecarga para comprobar el bloqueo. Esto no importará mucho. Java 6 en adelante, tiene un bloqueo de bloqueo en la JVM - http://java.sun.com/performance/reference/whitepapers/6_performance.html )

Por ejemplo, eche un vistazo al código fuente de java.util.Vector. Hay muchas llamadas a otros métodos sincronizados desde métodos sincronizados.

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