util threads practice example concurrent concurrencia java concurrency

threads - java util concurrent example



Java: un método sincronizado en la superclase adquiere el mismo bloqueo que uno en la subclase, ¿verdad? (7)

Desde el punto de vista conceptual, la integridad de mutex de algunos escenarios de herencia se rompería si los métodos synchonized de la clase A solo protegieran los datos de A en el contexto de la subclase B Después de todo, no todos los datos de A tienen que ser private .

Imagine que desea ampliar ligeramente la funcionalidad de un método de A mientras mantiene el resto de la funcionalidad de A , incluida la protección de exclusión mutua. Si A solo se estuviera protegiendo a sí mismo, tendría que anular todos los métodos synchronized para elevar el mecanismo de sincronización original a la nueva subclase. No muy atractivo y tampoco muy eficiente.

class A { public synchronized void myOneMethod() { // ... } } class B extends A { public synchronized void myOtherMethod() { // ... } } // ... B myObject; // ... myObject.myOneMethod(); // acquires lock myObject.myOtherMethod(); // same lock?

Como entiendo el modelo de sincronización, diría que sí, sí, porque el bloqueo / monitor está asociado con la instancia myObject, y no importa dónde se definió el método. Pero estoy en lo cierto? Si no, ¿por qué? Si es así, ¿por qué estás seguro, y yo no? :-)


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

Para ser más precise :

Para un método de clase (estático), se utiliza el bloqueo asociado con el objeto Clase para la clase del método. Para un método de instancia, se utiliza el bloqueo asociado con esto (el objeto para el que se invocó el método).


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

Tenga en cuenta que si los métodos fueran estáticos , se sincronizarían en diferentes objetos, es decir, sus respectivas clases (A y B).

EDITAR : ¿Por qué estoy seguro? No lo sé, ¿por qué no estás seguro? ;-) myObject es solo un objeto: no hay ninguna distinción entre los atributos de myObject que provienen de la clase A y los que provienen de la clase B. (Bueno, técnicamente, probablemente puedas usar la reflexión para descubrir cuáles son cuáles, entonces hay debe haber alguna distinción, pero olvídate de la reflexión por ahora. Para operaciones comunes en el objeto no hay distinción.)


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

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


Si desea ser más explícito sobre su bloqueo, 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 Java Concurrency in Practice , sección 4.2.1 "El patrón del monitor de Java". De esa manera usted sabe exactamente de dónde viene su monitor.


Solo una pequeña adición para las personas que podrían estar interesadas en el futuro.

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


sí, estás en lo correcto

Cuando un subproceso está ejecutando un método sincronizado para un objeto, todos los demás subprocesos que invocan métodos sincronizados para el mismo bloque de objeto (suspender ejecución) hasta que el primer subproceso finalice con el objeto. En este caso el objeto es B.