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:
- 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
- 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.
- En el diagrama de secuencia, desplace la vista horizontalmente para buscar Fork.<número
de id> y pulse para seleccionarlo.

- 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.

- 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".

- 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*.
- 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:
- 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.
- En la vista Hebras, pulse el botón de menú desplegable y pulse Abrir vista de pila de
llamadas.
- 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.
- 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.
- 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.
- 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:
- 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.
- 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.
- Comente Sleep.
- 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.