Tout d’abord un peu de théorie. Les class Vector et Hashtable sont des classes dont les accès sont synchronisés. Si 2 Threads manipulent un Vector, nous sommes sûrs que l’état de ce Vector est consistant et nous n’avons pas de problèmes d’accès concurrents. Ensuite Java 2 a introduit un nouvel ensemble de class « Collections » qui sont un formalisme de l’interface Collection et de l’interface Map. Ainsi la class Hashtable dans Java 2 implémente l’interface Map, et la class ArrayList est identique à la class Vector. Il y a cependant une différence de taille: ces nouvelles classes ne sont pas synchronisées. Un object ArrayList sans protections particulières de notre part, n’est pas synchronisé.
Quel est l’intérêt ?
A partir du moment où la m©thode add(Object O)
de la class ArrayList par exemple n’est pas synchronisé, vous pouvez maintenant effectuer plusieurs opérations au sein d’un bloc synchonized dans votre code.
Exemple:
Dans cet exemple simpliste nous voulons ajouter 1 objet à la fois dans un Vector. Une autre thread est susceptible d’utiliser la méthode getLastest ici. Comme la class Vector est synchronisé il n’est pas
nécessaire et même inutile de rajouter 2 synchronized sur nos méthodes. Cela reviendrait à avoir
2 synchronisations imbriquées avec un risque d’interbloquage.
private Vector list=new Vector(); public void storeId(Object first){ list.add(first); } public Object getLastest() { return list.lastElement(); }
Cependant si nous voulons enregistrer 2 objets à la fois à l’aide d’une seule méthode et que notre getLastest() ne puisse retourner une valeur qu’une fois nos 2 ajouts effectués alors nous aurions le code suivant:
private Vector list=new Vector(); public synchronized void storeIds(Object first,Object second){ list.add(first); list.add(second); } public synchronized Object getLastest() { return list.lastElement(); }
et là nous avons un soucis. En entrant dans la méthode storeIds, Java acquiert un verrou et bloque la lecture sur ce vecteur. Ensuite lorsque nous effectuons nos 2 opérations add() nous avons à chaque fois un autre verrou qui est inutile…
La solution est d’utiliser un objet ArrayList non-synchronisé et de synchroniser nous-même les accès. A noter que l’instance est privée car nous ne voulons pas qu’une autre class référence directement notre liste. En règle générale le référencement externe des variables d’instance d’une class est quelque chose à éviter. Autant refaire du C sinon.
private ArrayList list = new ArrayList(); public void storeIds(Object first,Object second){ synchronized(list){ list.add(first); list.add(second); } } public synchronized Object getLastest() { synchronized(list){ return list.lastElement(); } }
Voili voilà…
0 no like