Ejercicio 1.4: Resolución del cuello de botella de hebras

Antes de empezar, complete el Ejercicio 1.3: Identificación de un cuello de botella de hebras.

Para localizar el punto muerto en el código, puede utilizar el Diagrama de secuencia UML2 (las vistas Interacciones de objetos e Interacciones de hebras) y el recurso de perfilado Pila de llamada en el Monitor de perfilado, además de la vista Hebras.

Para resolver este punto muerto, averigüemos en primer lugar qué llamadas a método y qué objetos están implicados en el problema:

  1. En la vista Hebras, busque la primera hebra philo* que haya entrado en un estado del tipo "Se espera un bloqueo". Coloque el cursor sobre el segmento "Se espera un bloqueo". La información sobre la herramienta identifica el bloqueo que la hebra espera: Fork.<id number>.
  2. Pulse el botón derecho del ratón sobre el recurso Perfilado de la ejecución, y seleccione Abrir con > Interacciones de objetos UML2. Se abre la vista Diagrama de secuencia UML2, en la que se muestran las interacciones de objetos.
  3. En el diagrama, desplácese por la vista para encontrar Fork.<id number> y efectúe una doble pulsación en el mismo, para seleccionarlo.
  4. Desplácese hacia abajo para encontrar una flecha horizontal que va de una de las hebras philo* a Fork.<id number>. Dichas flechas muestran las interacciones que hay entre los objetos, y la primera interacción entre estos dos objetos indicará que la hebra philo* ha adquirido Fork.<id number>. Encontrará una flecha de dicho tipo, cuya etiqueta es getName.
  5. Efectúe una doble pulsación en getName. En la vista Hebras, el indicador Hora actual vertical se mueve para mostrar qué ha ocurrido en todo el programa cuando se ha llamado a getName. Puede ver que la petición ha finalizado correctamente, ya que la hebra philo* que marca la petición no entra en el estado "Se espera un bloqueo".
  6. En el diagrama de secuencias, vuelva a efectuar una doble pulsación en Fork.<id number>, y desplácese hacia abajo hasta encontrar una petición getName que se haya originado en una hebra philo* distinta.
  7. Efectúe una doble pulsación en esta instancia de getName. En el indicador Hora actual se mostrará que la hebra philo* que marca la petición no obtiene Fork.<id number>, y que entra en un estado "Se espera un bloqueo".

En esta instancia, el problema es una petición para un método Fork, retenida por otra hebra. Compruebe otras hebras que terminen en el estado "Se espera un bloqueo" para verificar que esta afirmación también sea cierta en otras instancias.

Ahora, intentaremos encontrar el método que provoca el problema.

  1. Pulse el botón derecho del ratón sobre el recurso Perfilado de la ejecución, y seleccione Abrir con > Interacciones de hebras UML2. Se abre la vista Diagrama de secuencia UML2, en la que se muestran las interacciones de hebras.
  2. En el Monitor de perfilado, expanda el recurso Perfilado y, a continuación, las entradas Análisis de hebras y Pila de llamada.
  3. En la vista Hebras, donde se visualizan los nombres de las hebras, efectúe una doble pulsación en la primera de las hebras philo* que entre en el estado "Se espera un bloqueo". Tenga en cuenta que la vista Interacciones de hebras cambia para visualizar información sólo de dicha hebra.
  4. Desplácese hacia abajo hasta llegar al final de la información de la hebra, y efectúe una doble pulsación en el último método que la hebra haya ejecutado: el método run. En la opción Pila de llamada del Monitor de perfilado se visualizan todas las llamadas que contiene la pila en ese momento.
  5. En Pila de llamada, observe que la hebra que retiene el bloqueo ha llamado al método Sleep de Philosopher.java; o que también espera un bloqueo y, por consiguiente, no hace nada.
  6. Compruebe las demás hebras que finalicen la ejecución esperando un bloqueo; a menudo, el método Sleep de Philosopher.java es la Pila de llamada, y éste puede ser el problema.

Ahora sospechamos del método Sleep. Veamos el código utilizado:

  1. En Pila de llamada, pulse el botón derecho del ratón sobre una instancia de Sleep(int) void [Philosopher.java] y seleccione Abrir origen. El origen se abre en el editor, en la ubicación de la clase Sleep.
  2. Examine el código. Tenga en cuenta que el método Sleep se llama desde el método run. En primer lugar se produce una llamada a trace, que ofrece el mensaje "quedaban..." y, a continuación, la llamada a Sleep. Al comentar la llamada Sleep, probablemente podemos evitar el punto muerto.
  3. Comente Sleep.
  4. Seleccione Archivo > Guardar.
Ahora, vuelva a perfilar el programa.

Esta vez, se ejecuta sin llegar a un punto muerto y, en la consola, escribe lo siguiente:

HeadWaiter reports all philosophers have finished dining normally

Como puede ver, la vista Hebras y las demás vistas muestran qué ocurre a las hebras a medida que se ejecuta el programa. Puede decidir si desea efectuar el análisis y resolver el punto muerto, en función de los conocimientos que tenga del programa.

Finalice la guía de aprendizaje revisando los materiales de la sección Resumen.

Condiciones de uso | Información de retorno
(C) Copyright IBM Corporation 2000, 2005. Todos los derechos reservados.