Modificações concorrentes

Mesmo programando há algum tempo em Java, há excepções que nos surpreendem e nos mostram que até somos capazes de não perceber nada disto.

Um colega obtinha, por vezes, uma excepção ConcurrentModificationException ao percorrer uma lista com um iterador. O código era uma versão mais complexa do seguinte excerto:

List lista = new ArrayList();
lista.add("obj1");
lista.add("obj2");
for(Iterator it=lista.iterator();it.hasNext();) {
    String elem = (String) it.next();
    if("obj1".equals(elem)) {
        lista.add("elem3");
    }
}

O que acontecia era, se uma condição se verificasse, era removido um elemento da lista. Quando tal acontecia, a próxima vez que o método next() do iterador fosse executado, obtínhamos a excepção. Ao olhar para o nome da excepção

, a primeira ideia foi que, dado a lista não ser sincronizada, estavam threads concorrentes a aceder ao objecto. No entanto, a conclusão foi mais simples e lógica.

Quando se

altera a estrutura de uma lista – adicionando ou removendo elementos – à qual está ligado um iterador que estamos a percorrer, esse iterador fica inválido. Limita-se a verificar se fizemos operações que alterassem a lista, se sim, lança uma ConcurrentModificationException. Não que seja um nome de excepção adequado.

A este comportamento dá-se o nome de fail-fast, pois o iterador lança a excepção mal detecta que existiu uma alteração à lista e não fica à espera que ocorra um erro, não determinístico, mais tarde, ao percorrer o iterador.

De notar que o mesmo ocorre se usarmos o foreach do java 5 e removermos elementos.

zp8497586rq