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 seu código, é possível utilizar o Diagrama de Seqüência UML2 (as visualizações Interações de Objeto e Interações de Encadeamento) e a Call Stack View (Visualização Pilha de Chamada), além da Thread View (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, localizar o primeiro encadeamento philo* que entrar em um estado "Deadlock (Conflito)". Pause o cursor sobre o segmento "Deadlock (Conflito)". A dica de ferramentas indica o bloqueio (Fork.<id number>) e o encadeamento de bloqueio (Locking Thread.<name>), por exemplo:

Lock: Fork 10038
Locking Thread: philo#1

  1. Clique com o botão direito do mouse no recurso Profiling (Traçado de Perfil) para a execução e selecione Open With (Abrir com) > UML2 Object Interactions (Interações de Objeto UML2). A visualização Diagrama de Seqüência UML2 é aberta, exibindo as Interações do Objeto.
  2. No diagrama de seqüência, navegue na visualização horizontalmente para localizar Fork.<id number> e clique para selecioná-lo.

Diagrama de Seqüência Mostrando Interações de Objetos

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

Diagrama de Seqüência Mostrando getName

  1. Clique 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 ver que o pedido obteve êxito, pois o encadeamento philo* que está fazendo o pedido ainda não está no estado "Waiting for Lock (Aguardando Bloqueio)" ou "Deadlock (Conflito)".

Visualização de Encadeamentos Mostrando o Encadeamento philo* no Estado em Execução

  1. No diagrama de seqüência, clique em Fork.<id number> novamente e role para baixo para localizar o pedido getName que se originou em um encadeamento philo* diferente.
  2. Clique nessa instância do getName. O indicador Tempo Atual mostrará que o encadeamento philo* fazendo o pedido não obtém o Fork.<id number> e entra em um estado "Waiting for Lock (Aguardando Bloqueio)" e, em seguida, "Deadlock (Conflito)".

Nessa instância, um pedido por uma Bifurcação que está sendo suspensa por outro encadeamento é o problema. Verifique outros encadeamentos  em conflito para ver se isso é verdadeiro 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 Profiling (Traçado de Perfil) e selecione Open With (Abrir com) > UML2 Thread Interactions (Interações de Encadeamento UML2). A visualização Diagrama de Seqüência UML2 é aberta, exibindo as Interações do Encadeamento.
  2. Na visualização Encadeamento, clique no botão drop-down do menu e clique em Open Call Stack View (Abrir Visualização Pilha de Chamada).
  3. Na visualização Encadeamento, em que os nomes dos encadeamentos são exibidos, dê um clique duplo no primeiro dos encadeamentos philo* em conflito. 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 da informação do encadeamento e dê um clique duplo no último método que o encadeamento executou: o método run. A Call Stack View (Visualização Pilha de Chamada) exibe todas as chamadas na pilha naquele momento.
  5. Em Pilha de Chamada, note que o encadeamento que está mantendo o bloqueio chamou o método Sleep no Philosopher.java; ou que ele também está em conflito e, conseqüentemente, não está funcionando.
  6. Verifique os outros encadeamentos que finalizam a execução em um estado conflitante; o método Sleep no Philosopher.java está normalmente na Pilha de Chamada 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 Open source (Abrir origem). A origem é aberta no editor no local da classe Sleep.
  2. Examine o código. Note que o método Sleep é chamado pelo 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 File (Arquivo) > Save (Salvar).
Agora crie o perfil do programa novamente.

Nesse momento, ele é executado sem um conflito e gravado 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 este tutorial revisando os materiais no Resumo.

Feedback
(C) Copyright IBM Corporation 2000, 2005. Todos os Direitos Reservados.