¿Por qué debemos usar "while" para verificar la condición de la carrera y no "if"?

Usar un control if en lugar de verificar repetidamente en un ciclo es un error. Hay múltiples razones para usar el bucle.

Una es la "activación espuria", lo que significa que el método de espera puede regresar sin que se haya notificado el hilo: no es válido inferir, basado en el hilo que sale del método de espera, que debe haber sido notificado. Puede que esto no suceda mucho, pero es una posibilidad que debe manejarse.

Pero la razón principal es esta: cuando su hilo espera libera el bloqueo. Cuando recibe una notificación, no tiene el bloqueo y debe adquirirlo nuevamente antes de que pueda salir del método de espera. El hecho de que el hilo haya sido notificado no significa que sea el siguiente en la línea para obtener el bloqueo. Si el subproceso decide qué hacer en función de algo que sucedió cuando el subproceso no era propietario del bloqueo, varios subprocesos pueden haber tenido la oportunidad de actuar sobre el mismo objeto compartido entre el momento en que ocurrió la notificación y el momento en que el subproceso obtuvo el bloqueo, y el estado del objeto compartido puede no ser lo que su hilo cree que es. El uso de un bucle while permite que el subproceso verifique la condición que está esperando nuevamente, con el bloqueo retenido, lo que confirma que la condición aún es válida antes de continuar.

Respuesta 1

La necesidad del bucle se explica en el Javadoc para los waitmétodos:

Un subproceso también puede despertarse sin ser notificado, interrumpido o expirado, lo que se conoce como un despertar espurio. Si bien esto rara vez ocurrirá en la práctica, las aplicaciones deben protegerse contra él mediante la prueba de la condición que debería haber provocado que el hilo se haya despertado y continuar esperando si la condición no se cumple.

Para evitar esto, después de que la wait()llamada regrese, debe verificar la condición nuevamente y, si es falsa, regresar y llamar wait()nuevamente en lugar de continuar. El whileciclo logra eso.


Cuando llama wait(), el bloqueo del objeto se libera automáticamente mientras espera y luego se vuelve a adquirir antes de que regrese el método. Esto significa que cuando otro subproceso llama notify()al objeto, el subproceso en espera no puede reanudar inmediatamente la ejecución, porque el subproceso de notificación aún mantiene el bloqueo del objeto y el subproceso en espera tiene que esperar a que se libere. También significa que si hay varios subprocesos en espera y usted llama notifyAll(), los subprocesos en espera no pueden reanudarse todos a la vez: uno de los subprocesos obtendrá el bloqueo y regresará wait(), y cuando se libere el bloqueo, entonces otro de los subprocesos puede adquirirlo y regresar de wait(), y así sucesivamente.

En algunos casos, cuando hay varios subprocesos en espera, un subproceso en espera puede despertarse, descubrir que la condición es verdadera y hacer algunas cosas que terminan cambiando la condición de nuevo a falso, todo mientras mantiene el bloqueo. Luego, cuando libera el bloqueo (por ejemplo, llamando de wait()nuevo), el siguiente subproceso se activa y descubre que la condición es falsa. En este caso, no es un despertar espurio; la condición realmente se volvió verdadera, pero luego se volvió falsa antes de que el hilo tuviera la oportunidad de verificarla.

Por ejemplo: un hilo productor agrega varios elementos a una cola y llama notifyAll()para despertar los hilos consumidores. Cada subproceso de consumidor toma un elemento de la cola, luego libera el bloqueo mientras procesa el elemento. Pero si hay más subprocesos de consumidores que elementos que se agregaron a la cola, algunos de los subprocesos se activarán solo para descubrir que la cola está vacía, por lo que solo tienen que volver a esperar.

La comprobación de la condición en un whilebucle se ocupa de esta situación además de manejar los despertares espurios.

Respuesta: 2

Estaba trabajando en una tarea escolar y descubrí algo llamado Enum. y pensé que era muy útil para mi tarea. así que decidí usarlo, pero cuando apareció este error. busqué en Google ...

He estado tratando de optimizar parte de mi código, y he llegado a una conclusión extraña con respecto a fors. En mi caso de prueba, he creado un nuevo proyecto con actividad principal. La actividad inicializa una Lista de 500 ...

Había usado eclipse para desarrollar aplicaciones de Android que pueden permitir al usuario registrarse. Después de registrarse con éxito y acceder a la página principal, pueden ver su propio perfil, que consiste en ...

Captura de pantalla del tamaño original Captura de pantalla completa Cuando cambio el tamaño, ¿cómo puedo organizar bien los componentes? estoy usando FXML para la GUI FXML CODE <AnchorPane id = "AnchorPane" prefHeight = "400.0" ...