2009-03-09 14 views
16
class A { 
    public synchronized void myOneMethod() { 
     // ... 
    } 
} 

class B extends A { 
    public synchronized void myOtherMethod() { 
     // ... 
    } 
} 

// ... 

B myObject; 

// ... 

myObject.myOneMethod(); // acquires lock 
myObject.myOtherMethod(); // same lock? 

Cómo entiendo el modelo de sincronización, diría que sí, porque el bloqueo/monitor está asociado con la instancia myObject, y no importa dónde se haya definido el método. Pero estoy en lo cierto? Si no, ¿por qué? Si es así, ¿por qué estás seguro y yo no? :-)Java: un método sincronizado en la superclase adquiere el mismo bloqueo que uno en la subclase, ¿verdad?

Respuesta

12

Sí, tienes razón, y tienes la explicación correcta también. No hay mucho que agregar.

Nota que si los métodos eran estática, entonces ellos se sincronizan en diferentes objetos, es decir, sus respectivas clases (A y B).

EDIT: ¿Por qué estoy seguro? No lo sé, ¿por qué no estás seguro? ;-) myObject es sólo un objeto - no hay ninguna distinción entre los myObject atributos que vienen de la clase A y los que provienen de la clase B. (Bueno, técnicamente que probablemente se podría utilizar la reflexión para averiguar cuál es cuál, por lo que hay debe ser alguna distinción, pero olvídate de la reflexión por el momento. para las operaciones comunes en el objeto no hay distinción.)

7

Sí, sincronizada es equivalente a sincronizada (esto).

Para ser más precise:

Para un método de clase (estática), se utiliza el bloqueo asociado con el objeto de clase para la clase de método. Para un método de instancia, se utiliza el bloqueo asociado a esto (el objeto para el cual se invocó el método).

+0

Por ejemplo, métodos, sí. –

1

Sí. Java usa "monitores" para implementar la sincronización, y los métodos sincronizados usan la instancia de objeto a la que se llama como monitor, que obviamente es lo mismo en este caso.

¡Tenga en cuenta que esto NO es cierto para los métodos estáticos! Allí, se utiliza la instancia de clase de (creo) la clase declarante, que no sería la misma.

0

Sí que son correctas

Cuando un hilo está ejecutando un método sincronizado para un objeto, todos los otros hilos que invocan métodos sincronizados para el mismo bloque objetivo (suspender la ejecución) hasta que el primer hilo se realiza con el objeto. En este caso el objeto es B

3

Si quieres ser más explícito acerca de su bloqueo, se podría hacer algo como esto:

class A { 

    protected final Object mutex = new Object(); 
    public void myOneMethod() { 
     synchronized (mutex) { 
      // ... 
     } 
    } 
} 

class B extends A { 
    public void myOtherMethod() { 
     synchronized (mutex) { 
      // ... 
     } 
    } 
} 

De hecho, este patrón es recomendado por Brian Goetz en concurrencia de Java en la práctica, sección 4.2.1 "El patrón del monitor de Java". De esta forma sabrá exactamente de dónde viene su monitor.

+0

Sí. Además, esto es lo que hace Jon Skeet: http://stackoverflow.com/questions/609963/java-what-if-anything-is-locked-by-synchronized-methods-apart-from-the-object/609981#609981 ;) Usaré ese patrón, excepto aquellos métodos en los que realmente tiene más sentido bloquear "esto". –

+0

Gracias por mencionar este enfoque. Aún así, la Q original puede referirse a una clase A proveniente de una biblioteca. Al menos, es por eso que busqué el tema. En ese caso, parece que entran en juego consideraciones adicionales. –

0

Sólo una pequeña adición para las personas que puedan estar interesadas en el futuro ..

Además recordar que los bloqueos en Java son reentrantes. Si no fuera así, este código resultaría en un punto muerto ya que, como ha indicado, ambas operaciones requieren el mismo bloqueo.

0

Desde el punto de vista conceptual, la integridad de exclusión mutua de algunos escenarios de herencia se rompería si synchonized métodos de la clase A además de proteger los datos A 's en el contexto de la subclase B. Después de todo, no todos los datos de A deben ser private.

Imagínese que desea ampliar ligeramente la funcionalidad de un método de A, manteniendo el resto de la funcionalidad A 's incluyendo la protección de exclusión mutua. Si A solo se estuviera protegiendo, terminaría teniendo que sobrescribir todos de A's synchronized métodos para levantar el mecanismo de sincronización original a la nueva subclase. No es muy atractivo y tampoco es muy eficiente.

Cuestiones relacionadas