US

Niveau de sécurité

Quand peut-on partager un objet entre plusieurs threads en toute sécurité, sans risquer de voir l'état de cet objet corrompu ou avoir des problèmes de cohérence entre ce que voit chaque thread sur l'état de l'objet ? Afin de répondre à cette question, des niveaux de sécurité ont été définis. Vous devriez toujours documenter vos classes en fonction de ces niveaux, pour permettre aux programmeurs qui utilisent vos classes de savoir dans quelle mesure ils peuvent les utiliser dans des programmes concurrents.

Cinq niveaux ont été définis et sont résumés par Joshua Bloch dans son livre Effective Java. Voici les cinq niveaux, le premier étant le plus sûr, et les suivants étant de moins en moins sûrs :

  1. Immutable ;
  2. Unconditionally Thread-Safe ;
  3. Conditionally Thread-Safe ;
  4. Not Thread-Safe ;
  5. Thread-Hostile.

On va maintenant décrire chacun de ces niveaux, l'un après l'autre, en donnant à chaque fois un exemple minimal ainsi que des exemples de classes de la librairie standard Java se trouvant dans ces niveaux.

Objet immuable

Les objets immuables sont des objets dont l'état ne change jamais, une fois l'objet créé. Ces objets apparaissent donc comme des constantes et peuvent être partagé sans aucun problème entre plusieurs threads. En effet, toutes les méthodes de ces objets vont à chaque fois créer de nouvelles instances. Dans la librairie standard Java, on retrouve notamment les classes String, les wrappers des types primitifs (Double, Long, Integer, ...), la classe BigInteger, ...

Objet thread-safe

Les objets thread-safe sont mutables, c'est-à-dire que leurs états peut-être modifié. Néanmoins, la classe utilise le mécanisme de synchronisation dans son implémentation interne, et garantit dès lors que son état sera toujours correct lorsque cet objet est partagé entre plusieurs threads. Avec cette garantie, on peut donc utiliser de tels objets sans aucune précaution particulière. On retrouve notamment les classes Random et ConcurrentHashMap dans la librairie standard Java.

Objet thread-safe sous condition

Contrairement aux objet thread-safe, il y en a également qui sont thread-safe sous condition. Cela signifie que certaines des méthodes de tels objets nécessitent d'utiliser de la synchronisation externe afin de pouvoir les utiliser entre plusieurs threads. Par exemple, pour les collections renvoyées par la méthode Collections.synchronized, il faut synchroniser l'utilisation de leurs itérateurs.

Objet non thread-safe

Pour utiliser les objets non thread-safe à partir de plusieurs threads, il faut obligatoirement appliquer de la synchronisation externe. Parmi ces classes, on retrouve beaucoup de classes de collection comme ArrayList et HashMap par exemple.

Objet hostiles au thread

Enfin, il reste la dernière catégorie qui sont les objets hostiles aux threads. Comme leur nom l'indique, ces objets ne peuvent jamais être partagés entre plusieurs threads, peu importe que vous utilisiez ou pas de la synchronisation externe. Bien entendu, personne n'écrit de telle classe par construction, il s'agit juste d'un manque de prise en compte de l'aspect concurrentiel lors de leurs écritures. Par exemple, la méthode System.runFinalizersOnExit est hostile aux threads et a par ailleurs été dépréciée.

En conclusion à ce chapitre, il faut être conscient que lorsqu'un objet est partagé entre plusieurs threads, il faut faire très attention lors de son utilisation. Selon le niveau de sécurité de l'objet, on pourra l'utiliser de manière tout à fait classique, ou il faudra utiliser le mécanisme de synchronisation vu dans ce chapitre, tout en faisant attention aux deadlocks.

De même, lorsque vous définissez vos propres classes, il faudra faire attention aux aspects de concurrence, et surtout, documenter la prise en compte ou non de ces aspects de concurrence, et s'il est connu, le niveau de sécurité de la classe.

  • Espace membre
  • Learning Center
  • Les forums
  • Livre d'or
  • Imprimer
  • Boutique
  • Info
  • Règlement
  • Erreur
  • Newsletter