2012-04-17 12 views
20

Tengo dos hilos Thread1 y Thread2objeto sincronizado configurado en nulo

//Within Thread1  
synchronized(obj1) 
{ 
    obj1 = null; 
} 

//Within Thread2 
synchronized(obj1) 
{ 
    do something 
} 

Si JVM ejecuta primero Thread1 y establece obj1 a nula, entonces se Thread2 ver que el cambio inmediatamente o va a tomar tiempo y JVM todavía podría funcionar el bloque synchron2 thread2 ya que obj1 aún no es nulo?

+7

@ KorhanÖztürk No pudo probarlo, cualquier tipo de problema relacionado con la concurrencia no es determinista. Este tipo de comentarios son extremadamente frustrantes cuando no se conoce el contexto. –

Respuesta

28

Esto casi seguramente romperá la abstracción de sincronización - No estoy seguro de que thread2 verá el cambio inmediatamente. Nunca debe cambiar la referencia del objeto en el que se está sincronizando, mucho menos configurarlo en null, lo que causará un NullPointerException en cualquier otro intento de sincronización en él.

9

Primero déjame enfatizar que modificar una variable que se usa para la sincronización es un terriblemente malo ™. obj1 debe ser final y nunca ser tocado si se utiliza como monitor.

Dicho esto, volviendo a tu pregunta:

Si JVM ejecuta primero Thread1, se sincroniza en obj1, lo establece en null y el hilo termina. El segundo hilo desea sincronizar en obj1, se lanzará NullPointerException. Debido a que la modificación de obj1 se realizó en bloque sincronizado, se garantiza que Thread2 verá el valor actualizado (así que: NullPointerException está garantizado).

Si Thread1 se interrumpe después de obtener el bloqueo en obj1 pero antes de borrar la referencia, Thread2 se bloqueará en obj1 y esperar hasta que finalice Thread1. Luego ingresará con éxito en el monitor porque aún existe el objeto al que se hizo referencia anteriormente en obj1.

+0

dado que obj1 se está utilizando en la condición sincronizada y no en el bloque sincronizado, no es posible que ambos subprocesos intenten sincronizarse al mismo tiempo y thread1 entra primero y thread2 almacena en caché el valor de obj1.cuando thread1 sale de thread2 toma el valor de obj1 de la caché y entra al bloque sincronizado y ve el cambio dentro del bloque sincronizado – vjk

+0

@Tomsaz No recibí esta afirmación suya _Si Thread1 se interrumpe después de obtener el bloqueo en obj1 pero antes de borrar la referencia, Thread2 se bloqueará en obj1 y esperará hasta que Thread1 termine_ Ahora, antes que nada, interrumpimos el hilo solo cuando están bloqueados y, de todos modos, si no están bloqueados, interrumpirlos no tiene ningún efecto, ¿no? Básicamente, nunca veo un caso en el que thread1 renuncie al bloqueo sin completar el bloqueo sincronizado o sin que wait() se llame a ese bloqueo. IOW, cuándo y por qué thread2 obtendría el bloqueo, pero aún esperaría a que thread1 termine. – sactiw

4

synchronized se sincroniza en el objeto y no en la referencia. Al establecer obj1 (una referencia) en nulo, thread2 no se puede sincronizar en el objeto anteriormente apuntado por obj1, obtendrá un NullPointerException en su lugar.

0

El cambio es inmediato. Cuando el Tema 1 "posee" el bloqueo, puede cambiar el valor de obj1 a voluntad. El hilo 2 tiene que esperar hasta que el hilo 1 libere el bloqueo. Definitivamente va a ver obj1 == null

1

Una solución rápida es para que el objeto una simple matriz de 1 elemento y se refieren a la matriz para la sincronización, por ejemplo,

Object [] obj1 = {null};

El elemento puede ser nulo sin afectar la existencia del conjunto. Por supuesto, esto aún rompe la "regla" de no usar el objeto mismo en sincronización, pero a menos que su código complique las cosas en otra parte, esta solución rápida debería funcionar como se esperaba.

Cuestiones relacionadas