décembre
2005
Dans un environnement multi-thread, on peut se retrouver dans un état incohérent si un thread modifie des données pendant qu’un autre est en train de les lire. Pour éviter cela, il est nécessaires de synchroniser les accès aux données en utilisant un mécanisme d’exclusion mutuelle qui permet de s’assurer que les données ne seront utilisées que par un seul thread à la fois…
Java permet de gérer cela simplement avec le mot-clef synchronized. Toutefois, si le coût de la synchronisation est presque nulle, cela peut provoquer de piètre performance si les données sont utilisées très souvent par de nombreux threads, puisqu’un seul ne pourra y accéder à la fois, et que les autres devront attendre leur « tour »…
Pourtant dans bien des cas ce principe d’exclusion mutuelle est un peu trop restrictive, puisque les problèmes ne surviennent que lorsqu’il y a une modification des données.
Tiger (Java 5.0) a introduit une nouvelle API de synchronisation, qui permet entre autre de gérer des cas de synchronisation plus complexe que la simple exclusion mutuelle…
Je ne m’attarderais pas sur les nombreuses possibilités de ce nouveau package (java.util.concurrent.locks), mais simplement sur l’interface ReadWriteLock (et son implémentation par défaut ReentrantReadWriteLock) qui va nous permettre d’obtenir une meilleure gestion de la synchronisation que l’exclusion mutuelle, en se basant sur le fait que les threads qui ne font que lire les données peuvent très bien s’exécuter en parallèle du moment qu’aucun thread ne modifie ces même données…
Cette interface décrit donc deux méthode qui renvoient deux Lock : un pour la lecture, et un pour l’écriture. Elle définit donc les méthodes suivantes :
public Lock readLock();
public Lock writeLock();
L’intérêt de de pouvoir différencier le type d’utilisation des données, afin d’autoriser des accès « simultanées » en lecture lorsqu’aucun thread n’utilise les données en écriture.
Ainsi le code suivant autorisera plusieurs thread à lire les données :
myLock.readLock().lock();
try {
// Accès aux données en lecture...
} finally {
myLock.readLock().unlock();
}
Du moment qu’aucun thread n’utilise le lock d’écriture :
myLock.writeLock().lock();
try {
// Accès aux données en écriture...
} finally {
myLock.writeLock().unlock();
}
A l’inverse le lock d’écriture writeLock() ne sera attribué à un thread que si aucun autre thread n’utilise le lock de lecture ou le lock d’écriture.
Le lock d’écriture conserve le principe d’exclusion mutuelle en n’autorisant qu’un seul thread à accéder aux données (en lecture ou écriture), alors que le lock de lecture permet à plusieurs thread d’accéder aux données du moment qu’aucun d’entre eux ne les modifie…
Bien entendu la cohérence de l’utilisation de ces locks est à la charge du développeur…
3 Commentaires + Ajouter un commentaire
Tutoriels
Discussions
- L'apparition du mot-clé const est-il prévu dans une version à venir du JDK?
- Définition exacte de @Override
- Difference de performances Unix/Windows d'un programme?
- Recuperation du nom des parametres
- jre 1.5, tomcat 6.0 et multi processeurs
- [REFLEXION] Connaitre toutes les classes qui implémentent une interface
- Classes, méthodes private
- Possibilité d'accéder au type générique en runtime
- [ fuite ] memoire
Non, ce n’est pas plus dangereux qu’un synchronized standard qui lui aussi doit être interdit à haut niveau.
En fait, le problème qui se pose est lors de l’intégration de 2 codes provenant de 2 programmeurs qui chacun de leur côté ont vérifié la cohérence de l’utilisation de ces locks mais n’ont pas réfléchi à haut niveau.
Bien entendu il faut utiliser cela avec précaution, mais je ne pense pas que ce soit plus dangereux qu’un synchronized standard…
Et comme je l’ai dit : « Bien entendu la cohérence de l’utilisation de ces locks est à la charge du développeur… »
a++
Il devrait être interdit d’utiliser de telles fonctions à de haut niveau, car les interblocages sont alors difficilement détectables.
De manière générale, il faudrait systématiquement utiliser ces méthodes pour implémenter des outils de synchronisation de haut niveau.
Nous venons d’en faire l’amère expérience…