variable sirve sincronizar sincronizados que productores productor procesos para hilos fuente ejemplos consumidores consumidor codigo acceso java concurrency synchronization

sirve - synchronized java netbeans



Sincronización en un objeto en java, luego cambiando el valor de la variable sincronizada. (4)

Es un uso poco común pero parece ser válido en los mismos escenarios. Una que encontré en el código base de JmDNS:

public Collection<? extends DNSEntry> getDNSEntryList(String name) { Collection<? extends DNSEntry> entryList = this._getDNSEntryList(name); if (entryList != null) { synchronized (entryList) { entryList = new ArrayList<DNSEntry>(entryList); } } else { entryList = Collections.emptyList(); } return entryList; }

Lo que hace es sincronizar en la lista devuelta para que otros no modifiquen esta lista y luego haga una copia de esta lista. En esta situación especial, el bloqueo solo es necesario para el objeto original.

Me encontré con un código como este

synchronized(obj) { obj = new Object(); }

Algo no se siente bien con respecto a esto, no puedo explicarlo. ¿Está bien este fragmento de código o hay algo realmente incorrecto en él? Indíquelo. Gracias


Este es un caso en el que alguien podría pensar que lo que están haciendo está bien, pero probablemente no es lo que pretendían. En este caso, está sincronizando el valor actual en la variable obj. Una vez que cree una nueva instancia y la coloque en la variable obj, las condiciones de bloqueo cambiarán. Si eso es todo lo que está ocurriendo en este bloque, probablemente funcionará, pero si está haciendo algo más después, el objeto no se sincronizará correctamente.

Es mejor estar seguro y sincronizarse con el objeto que lo contiene o con otro mutex por completo.


Probablemente no es lo que quieres hacer. Estás sincronizando en un objeto al que ya no tienes una referencia. Considere otro hilo que ejecuta este método: pueden ingresar e intentar cerrar el bloqueo en el momento posterior a la actualización de la referencia a obj para apuntar al nuevo objeto. En ese momento, se están sincronizando en un objeto diferente al primer hilo. Esto probablemente no es lo que estás esperando.

A menos que tenga una buena razón para no hacerlo, es probable que desee sincronizar en un Objeto final (por el bien de la visibilidad). En este caso, probablemente desee usar una variable de bloqueo separada. Por ejemplo:

class Foo { private final Object lock = new Object(); private Object obj; public void method() { synchronized(lock) { obj = new Object(); } } }


Si obj es una variable local y ningún otro subproceso lo está evaluando para obtener un bloqueo como se muestra aquí, entonces no importa. De lo contrario, esto se rompe gravemente y se aplica lo siguiente:

(Publicar esto porque las otras respuestas no están lo suficientemente redactadas, "probablemente" no es suficiente aquí y no tienen suficientes detalles).

Cada vez que un subproceso encuentra un bloque sincronizado, antes de que pueda adquirir el bloqueo, tiene que averiguar qué objeto necesita bloquear, evaluando la expresión en parens siguiendo la palabra clave sincronizada.

Si la referencia se actualiza después de que el hilo evalúa esta expresión, el hilo no tiene forma de saberlo. Se procederá a adquirir el bloqueo en el objeto antiguo que identificó anteriormente como el bloqueo. Finalmente, ingresa el bloqueo del bloque sincronizado en el objeto anterior, mientras que otro subproceso (que intenta ingresar al bloqueo después de que el bloqueo haya cambiado) ahora evalúa el bloqueo como el nuevo objeto y ingresa el mismo bloque del mismo objeto que mantiene el nuevo bloqueo. Y no tienes exclusión mutua.

La sección relevante en el JLS es 14.19 . El hilo ejecutando la sentencia sincronizada:

1) evalúa la expresión, luego

2) adquiere el bloqueo en el valor que la expresión evalúa, luego

3) Ejecuta el bloque.

No vuelve a visitar el paso de evaluación en el momento en que adquiere el bloqueo con éxito.

Este código está roto. No hagas esto Cierra las cosas que no cambian.