Exercício 1.4: Resolvendo o Gargalo de Encadeamento

Antes de começar, você deve concluir o Exercício 1.3: Identificando um gargalo de encadeamento.

Para localizar o conflito no código, é possível utilizar o Diagrama de Seqüência UML2 (as visualizações Interações de Objeto e Interações de Encadeamento) e o recurso de criação de perfis Pilha de Chamadas no Monitor de Criação de Perfis, além da visualização Encadeamento.

Para resolver esse conflito, iremos primeiramente descobrir quais chamadas de métodos e quais objetos estão envolvidos no problema:

  1. Na visualização Encadeamento, localize o primeiro encadeamento philo* que entra em um estado "Aguardando por Trava". Pause o cursor sobre o segmento "Aguardando por Trava". A dica de ferramenta identifica a trava pela qual o encadeamento está aguardando: Fork.<id number>.
  2. Clique com o botão direito do mouse no recurso de Criação de Perfil para a execução e selecione Abrir Com >Interações do Objeto UML2. A visualização Diagrama de Seqüência UML2 é aberta, exibindo as Interações do Objeto.
  3. No diagrama de seqüência, role a visualização para localizar Fork.<id number> e dê um clique duplo para selecioná-la.
  4. Role para baixo para localizar uma seta horizontal a partir de um dos encadeamentos philo* para Fork.<id number>. Essas setas mostram interações entre objetos, onde a primeira interação entre esses dois objetos indicará que o encadeamento philo* obteve Fork.<id number>. Você localizará uma seta desse tipo rotulada getName.
  5. Dê um clique duplo em getName. Na visualização Encadeamento, o indicador vertical de Tempo Atual se move para mostrar o que estava ocorrendo no programa inteiro quando getName foi chamado. É possível verificar que o pedido obteve êxito, pois o encadeamento philo* que está fazendo o pedido não entra no estado "Aguardando por Trava".
  6. No diagrama de seqüência, dê um clique duplo em Fork.<id number> novamente e role para baixo para localizar um pedido getName que originou um encadeamento philo* diferente.
  7. Dê um clique duplo nessa instância de getName. O indicador Tempo Atual mostrará que o encadeamento philo* que faz o pedido não obtém Fork.<id number> e entra em um estado "Aguardando por Trava".

Nessa instância, um pedido por uma Bifurcação que está sendo suspensa por outro encadeamento é o problema. Verifique outros encadeamentos que terminam no estado "Aguardando por Trava" para verificar se isso também acontece em outras instâncias.

Agora vamos tentar localizar o método que está causando o problema:

  1. Clique com o botão direito do mouse no recurso de Criação de Perfil para a execução e selecione Abrir Com > Interações do Encadeamento UML2. A visualização Diagrama de Seqüência UML2 é aberta, exibindo as Interações do Encadeamento.
  2. No Monitor de Criação de Perfis, expanda o recurso de Criação de Perfil e, em seguida, a entrada Análise de Encadeamento e a entrada Pilha de Chamadas.
  3. Na visualização Encadeamento, onde os nomes dos encadeamentos são exibidos, dê um clique duplo no primeiro dos encadeamentos philo* que entra no estado "Aguardando por Trava". Note que a visualização Interações do Encadeamento é alterada para exibir informações apenas para esse encadeamento.
  4. Role para baixo até o final das informações do encadeamento e dê um clique duplo no último método executado pelo encadeamento: o método run. A Pilha de Chamadas no Monitor de Criação de Perfis exibe todas as chamadas na pilha nesse momento.
  5. Na Pilha de Chamadas, note que o encadeamento que está suspendendo a trava chamou o método Sleep em Philosopher.java; ou ainda que esteja aguardando por uma trava e, conseqüentemente, não está fazendo nada.
  6. Verifique os outros encadeamentos que finalizam a execução aguardando por uma trava; o método Sleep em Philosopher.java está freqüentemente na Pilha de Chamadas e pode ser o problema.

Agora suspeitamos do método Sleep. Vejamos o código:

  1. Na Pilha de Chamadas, clique com o botão direito do mouse em uma instância de Sleep(int) void [Philosopher.java] e selecione Abrir origem. A origem é aberta no editor e no local da classe Sleep.
  2. Examine o código. Note que o método Sleep é chamado de dentro do método run. Primeiramente há uma chamada para trace, que imprime a mensagem "got left..." e, em seguida, uma chamada para Sleep. Comentando a chamada para Sleep, possivelmente impediremos o conflito.
  3. Comente Sleep.
  4. Selecione Arquivo > Salvar.
Agora crie o perfil do programa novamente.

Desta vez ele é executado sem um conflito e grava no console:

HeadWaiter reports all philosophers have finished dining normally

Como é possível ver, a visualização Encadeamento e as outras visualizações mostram o que ocorre com os encadeamentos à medida que o programa é executado. Você é o responsável em analisar e resolver o conflito, com base em seu conhecimento do programa.

Conclua o tutorial revisando os materiais no Sumário.

Termos de uso | Feedback
(C) Copyright IBM Corporation 2000, 2005. Todos os Direitos Reservados.