quinta-feira, 8 de maio de 2008

Pegadinha de Concorrência

Um pouco antes do nosso primeiro encontro,
e já quase na hora de receber em casa minhas
companheiras de blog, recebo uma mensagem de msn
da Andrea, que estava junto da Cris:

30/4/2008  15:41:48  Andréa  Julia  Julia, você tá ocupada?
30/4/2008  15:41:55  Andréa  Julia  eu e Cris precisamos muito da sua ajuda... ;-)
30/4/2008  15:42:06  Julia  Andréa  Diga! :)
30/4/2008  15:42:32  Andréa  Julia  estamos com um erro de concorrencia, mas está tão absurdo que a gente acha que está fazendo algo errado
30/4/2008  15:42:43  Andréa  Julia  vou te mandar o programinha para voce rodar aí
30/4/2008  15:42:45  Andréa  Julia  pode ser?
30/4/2008  15:43:33  Julia  Andréa  Posso tentar ajudar sim, mas se vce e a Cris nao conseguiram, acho dificil eu conseguir... ;)
30/4/2008  15:43:36  Julia  Andréa  me manda

É claro que aceitei o desafio :-)
Problemas de concorrência são sempre divertidos
mas, esse em particular, faço questão de compartilhar
no blog. Não pela dificuldade em si, mas pela
sua característica de "não ser o que parece ser" ,
aliás tão comum na programação e na vida...

Logo depois, elas próprias identificaram o erro
mas eu confesso que, se as duas não fossem minhas amigas,
eu diria que elas estavam querendo me derrubar ;-)

É claro que já dei a entender que o código tem uma
"pegadinha", mas assim mesmo vou deixar vocês
descobrirem qual é ela e colocarem seus comentários
a respeito.

Segue o código "bichado", como a Cris o chamou.
O código está escrito em Java.

import java.util.*;

class Handler {
private Vector lista = new Vector();

public synchronized void altera() {
System.out.println("Entrou ALTERA");
for (String str : lista) {
lista.remove("123");
}
try {
Thread.sleep(1000);
}
catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println("Saiu ALTERA");
}

public synchronized void add(String a) {
System.out.println("Entrou ADD");
try {
lista.add(a);
Thread.sleep(1000);
}
catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println("Saiu ADD");
}

public synchronized void remove(String a) {
System.out.println("Entrou REMOVE");
try {
lista.remove(a);
Thread.sleep(1000);
}
catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println("Saiu REMOVE");
}

public static void main(String[] args) {
final Handler h = new Handler();
Thread t1 = new Thread() {
public void run() {
h.add("123");
h.remove("456");
h.altera();
}
};
Thread t2 = new Thread() {
public void run() {
h.add("456");
h.remove("123");
h.altera();
}
};
t1.start();
t2.start();
}
}

Um comentário:

Andrea disse...

Bom, respondendo a "pegadinha" que fizemos "sem querer" com a Julia... :-)

O nosso problema era uma exceção de concorrência que estava ocorrendo no sistema e resolvemos tentar reproduzi-la por fora. E nós conseguimos!!! ;-)

Rapidamente, resolvemos pedir ajuda da Julia, afinal a gente pensou: "Não é possível que o Java está com um furo desses!" Mais rapidamente ainda, vimos que o nosso exemplo é que estava "furado", e não conseguimos reproduzir o que queríamos, porque na verdade o Java funciona! rsssss

Aproveitei o post da Julia, para chamá-la para resolver comigo o problema "real" de concorrência que ainda existia no nosso sistema. Agora não era mais pegadinha!

Bom, hoje esse problema foi finalmente resolvido, com a participação das minhas amigas Cris e Julia! Ah, também contou com umas dicas do Mac, que já havia visto o post da Julia, e estava "doido" para descobrir o "furo", mas faltaram informações... ;-)

Até a próxima "pegadinha"!!