D'après moi, en regardant le code source de EventListenerList, il y a une erreur (ou plutôt un cas non géré) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
public synchronized <T extends EventListener> void add(Class<T> t, T l) {
    // c'est synchronized
}
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
public synchronized <T extends EventListener> void remove(Class<T> t, T l) {
    // c'est synchronized
}
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
// non synchronized
public <T extends EventListener> T[] getListeners(Class<T> t) {
    Object[] lList = listenerList; 
    int n = getListenerCount(lList, t); 
    T[] result = (T[])Array.newInstance(t, n); 
    int j = 0; 
    for (int i = lList.length-2; i>=0; i-=2) {
        if (lList[i] == t) {
	    result[j++] = (T)lList[i+1];
        }
    }
    return result;   
}
Le problème se trouve sur:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
Object[] lList = listenerList;
En effet, sur une machine MULTI-processeurs, un processeur P1 peut faire un getListeners, puis un autre P2 peut faire un add, suivi plus tard par un getListeners par le processeur P1.
Le 2e getListeners de P1 peut potentiellement ne pas voir la modification effectuée par le add de P2, même si le getListeners a lieu bien après (même si en pratique la probabilité est très faible). Ceci se produit si le cache de P1 n'a pas été invalidé (du moins pour la variable listenerList), ce qui est possible vu que la méthode getListeners n'est pas synchronisée et que listenerList n'est pas volatile.

Même si on peut considérer que getListeners est faite en théorie pour être exécutée dans l'EDT, les add et remove peuvent être appelés de l'extérieur (sinon ils ne seraient pas synchronized).

On pourrait certes considérer que le niveau de cohérence ne soit pas la "cohérence séquentielle", et que les lectures peuvent être anciennes, mais ça serait une hypothèse un peu trop faible...

Je peux me tromper, mais ça ne serait pas la première fois que la synchronisation n'est correcte dans java (avant java 1.5, volatile ne marchait pas, et les moniteurs ne pouvaient avoir qu'une variable condition).

Qu'en pensez-vous?