Ejercicio 1.4: Resolver el cuello de botella de hebra

Antes de empezar, complete el Ejercicio 1.3: Identificar un cuello de botella de hebra.

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

Para resolver este punto muerto, descubra primero qué llamadas de método y qué objetos están involucrados en el problema:

  1. En la vista Hebra, busque la primera hebra philo* que entra en estado de "Punto muerto". Sitúe el cursor sobre el segmento "Punto muerto". La ayuda flotante identifica el bloqueo (Fork.<número de id>) y la hebra de bloqueo (Hebra de bloqueo.<nombre>), por ejemplo:

Bloqueo: Fork 10038
Hebra de bloqueo: philo#1

  1. Pulse el recurso Perfilado con el botón derecho del ratón para ejecutarlo y seleccione Abrir con > Interacciones de objeto UML2. Se abre la vista Diagrama de secuencia UML2 en la que se visualizan Interacciones de objeto.
  2. En el diagrama de secuencia, desplace la vista horizontalmente para buscar Fork.<número de id> y pulse para seleccionarlo.

Diagrama de secuencia que muestra interacciones de objetos

  1. Desplácese para buscar una flecha horizontal de una de las hebras philo* a Fork.<número de id>. Estas flechas muestran interacciones entre objetos y la primera interacción entre estos dos objetos indicará que la hebra philo* ha adquirido Fork.<número de id>. Encontrará una flecha así con la etiqueta getName.

Diagrama de secuencia que muestra getName

  1. Pulse getName. En la vista Hebras, el indicador Tiempo actual se mueve para mostrar lo sucedido en todo el programa cuando se llamó a getName. Puede ver que la petición ha sido satisfactoria, ya que la hebra philo* que está haciendo la petición no está todavía en el estado "Esperando bloqueo" ni "Punto muerto".

Vista Hebras que muestra la hebra philo* en estado de ejecución

  1. En el diagrama de secuencia, pulse Fork.<número de id> de nuevo y desplácese para buscar una petición getName que se haya originado en otra hebra philo*.
  2. Pulse esta instancia de getName. El indicador Tiempo actual mostrará que la hebra philo* que hace la petición no obtiene Fork.<número de id> y que entra en un estado "Esperando bloqueo" y después pasa a un estado de "Punto muerto".

En esta instancia, el problema lo constituye una petición para un Fork mantenido por otra hebra. Compruebe otras hebras que estén en punto muerto para verificar que esto es cierto también en otras instancias.

Ahora vamos a intentar encontrar el método causante del problema:

  1. Pulse el recurso Perfilado con el botón derecho del ratón para ejecutarlo y seleccione Abrir con > Interacciones de hebra UML2. Se abre la vista Diagrama de secuencia UML2 en la que se visualizan Interacciones de hebra.
  2. En la vista Hebras, pulse el botón de menú desplegable y pulse Abrir vista de pila de llamadas.
  3. En la vista Hebras, en la que se visualizan los nombres de hebras, efectúe una doble pulsación sobre la primera de las hebras philo* en punto muerto. Tenga en cuenta que la vista Interacciones de hebras cambia para visualizar información solamente para esa hebra.
  4. Desplácese al final de la información para la hebra y efectúe una doble pulsación sobre el último método ejecutado por la hebra: el método run. La vista Pila de llamadas visualiza todas las llamadas de la pila en ese momento.
  5. En la Pila de llamadas, fíjese en que la hebra que mantiene el bloqueo ha llamado al método Sleep en Philosopher.java o que también está en punto muerto y en por tanto no está haciendo nada.
  6. Compruebe el resto de hebras que finalizan la ejecución en estado de punto muerto; el método Sleep de Philosopher.java se llama a menudo en la Pila de llamadas y puede ser el problema.

Ahora sospechamos del método Sleep. Demos un vistazo al código:

  1. En la Pila de llamadas, pulse con el botón derecho del ratón sobre una instancia de Sleep(int) void [Philosopher.java] y seleccione Abrir código fuente. El código fuente se abre en el editor en la ubicación de la clase Sleep.
  2. Examine el código. Tenga en cuenta que al método Sleep lo llama el método run. Primero hay una llamada a trace que imprime el mensaje "got left..." y después una llamada a Sleep. Si comentamos la llamada a Sleep, posiblemente podamos evitar el punto muerto.
  3. Comente Sleep.
  4. Seleccione Archivo > Guardar.
Ahora vuelva a perfilar el programa.

Esta vez se ejecuta sin un punto muerto y en la consola aparece escrito:

HeadWaiter reports all philosophers have finished dining normally

Como puede ver, la vista Hebras y las otras vistas muestran lo que le ocurre a las hebras al ejecutarse el programa. A usted corresponde realizar el análisis y resolver el punto muerto basándose en su conocimiento del programa.

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

Comentarios
(C) Copyright IBM Corporation 2000, 2005. Reservados todos los derechos.