studio programacion para intuitivas gratis español desarrollador curso con avanzado aplicaciones java multithreading concurrency wait java.util.concurrent

java - programacion - ¿Por qué espera la condición de bloqueo debe mantener el bloqueo



manual de java para android (5)

Bueno, ¿qué estamos esperando? Estamos esperando que se cumpla una condición. Otro hilo hará que la condición sea verdadera, luego notificará los hilos en espera.

Antes de entrar en espera, debemos comprobar que la condición es falsa; esta comprobación y la espera deben ser atómicas , es decir, bajo el mismo bloqueo. De lo contrario, si ingresamos a la espera mientras la condición ya es verdadera, es probable que nunca nos activemos.

Por lo tanto, es necesario que el bloqueo ya esté adquirido antes de llamar a wait()

synchronized(lock) { if(!condition) lock.wait();

Si wait() adquiere el bloqueo de forma automática y silenciosa, muchos errores no se detectarán.

Al despertar de la wait() , debemos verificar la condición nuevamente; no hay garantía de que la condición se cumpla aquí (por muchas razones: activación falsa, tiempo de espera, interrupción, múltiples camareros, múltiples condiciones)

synchronized(lock) { if(!condition) lock.wait(); if(!condition) // check again ...

Normalmente, si la condición sigue siendo falsa, esperaremos de nuevo. Por lo tanto el patrón típico es

while(!condition) lock.wait();

Pero también hay casos en los que no queremos esperar de nuevo.

¿Podría haber casos de uso legítimos en los que la espera / notificación sin sentido tenga sentido?

synchronized(lock){ lock.wait(); }

Por supuesto; una aplicación se puede hacer con un modo de espera / notificación simple, con un comportamiento bien definido; Se puede argumentar que este es el comportamiento deseado; y esta es la mejor implementación para ese comportamiento.

Sin embargo, ese no es el patrón de uso típico, y no hay razón para tenerlo en cuenta en el diseño de la API.

Tengo dudas con eso, en el lenguaje Java, necesitamos mantener el bloqueo, antes de esperar alguna condición para estar satisfechos.

por ejemplo, int java monitor lock:

synchronized(lock){ System.out.println("before lock ..."); lock.wait(); System.out.println("after lock ..."); }

o los utils cucurrent.

Lock lock = new ReentrantLock(); Condition cond = lock.newCondition(); lock.lock(); try{ System.out.println("before condition ..."); cond.await(); System.out.println("after condition ..."); }catch(Exception e){ e.printStackTrace(); }finally{ lock.unlock(); }

Entonces, ¿por qué no podemos esperar, sin mantener la cerradura?

¿Si eso solo por Java, otros lenguajes funcionan diferente?

Espero que pueda explicar la razón después del diseño, pero no solo para la definición de JAVA-SPEC.


Consulte el documento para la Condition .

Una condición es como un grupo de espera o un conjunto de espera de un objeto y reemplaza el uso de los métodos de supervisión de objetos (esperar, notificar y notificar a todos). Las condiciones permiten que un subproceso suspenda la ejecución (para "esperar") hasta que otro subproceso notifique que alguna condición de estado ahora puede ser verdadera. Una instancia de Condición está vinculada intrínsecamente a un bloqueo, al igual que los métodos del monitor Objeto requieren el bloqueo del objeto compartido para esperar o notificar. Entonces, antes de invocar await () en una condición, el hilo debe haber bloqueado el objeto de bloqueo que se usa para producir la condición. Cuando se invoca el método await (), se libera el bloqueo asociado con la condición.


Imagina que tienes algo que un hilo podría necesitar. Tal vez usted tenga una cola y un hilo deba esperar hasta que haya algo en la cola para que pueda procesarlo. La cola debe ser segura para subprocesos, por lo que debe estar protegida por un bloqueo. Podrías escribir el siguiente código:

  1. Adquirir el bloqueo.
  2. Compruebe si la cola está vacía.
  3. Si la cola está vacía, espere a que se coloque algo en la cola.

Vaya, eso no funcionará. Mantenemos el bloqueo en la cola, entonces, ¿cómo puede otro hilo colocar algo en él? Intentemoslo de nuevo:

  1. Adquirir el bloqueo.
  2. Compruebe si la cola está vacía.
  3. Si la cola está vacía, libere el bloqueo y espere a que se coloque algo en la cola.

Vaya, ahora todavía tenemos un problema. ¿Qué sucede si después de liberar el bloqueo pero antes de esperar a que se coloque algo en la cola, se coloca algo en la cola? En ese caso, estaremos esperando algo que ya sucedió.

Las variables de condición existen para resolver este problema exacto. Tienen una operación atómica de "desbloquear y esperar" que cierra esta ventana.

Así que espere debe mantener el bloqueo porque de lo contrario no habría manera de asegurarse de que no estaba esperando algo que ya sucedió. Debes mantener el bloqueo para evitar que otro hilo compita con tu espera.


La respuesta simple es porque de lo contrario obtendrá la excepción IllegalMonitorStateException que se especifica en Object.wait javadoc. Internamente, la sincronización en Java utiliza un mecanismo de SO subyacente. Así que no es solo Java.


Si el hilo simplemente estuviera esperando que se produjera una señal, hay otros mecanismos para hacerlo. Presumiblemente hay algún estado protegido por el bloqueo en el que el hilo está esperando para ser operado y cumple alguna condición. Para proteger adecuadamente ese estado, el hilo debe tener el bloqueo antes y después de esperar la condición, por lo que tiene sentido requerir la adquisición del bloqueo.