Bonjour tous le monde,
Est ce que quelqu'un à une idée sur les Thread safe [utilisation, fonctionnement]?
Merci d'avance
Version imprimable
Bonjour tous le monde,
Est ce que quelqu'un à une idée sur les Thread safe [utilisation, fonctionnement]?
Merci d'avance
Bonjour,
La notion de Thread Safe consiste à assurer qu'un objet peut être utilisé par plusieurs Thread simultané sans comportement hasardeux.
Pour cela, on s'assure que les opérations sensibles ne peuvent être accéder que par un Thread à la fois grâce au mot clé synchronized.
Pour plus d'informations, tu peux voir du cote du tuto : http://rom.developpez.com/java-synchronisation/
Bon courage.
Salut,
Les thread safe ne sont pas des objets : cela ne s'utilise pas !!!
La notion de thread-safe est un concept, qui dit qu'une methode ou un objet peut être utilisé depuis différents threads sans que cela ne pose de problème ou de résultat incohérent selon les actions effectué par les autres threads sur l'objet ou l'application...
Salut,
Tout à fait !
Si plusieurs threads manipules les même données on pourrait se retrouver dans de facheuse situation :(
Un code thread-safe est un code qui permet de gérer cela, afin de s'exécuter correctement en toute circonstance.
Bien sûr le déroulement des threads peut faire varier le résultat final, mais cela ne provoquera pas d'incohérence ni d'erreur.
Prenons par exemple le code suivant :
En l'état les méthodes setName() et getName() sont thread-safe (leurs exécutions ne sont pas impacté par les modifications extérieurs sur l'objet), car les opérations d'affectation sont atomique (attention ce n'est pas vrai sur les types float/double !).Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 class User { private String name; public void setName(String name) { this.name = name; } public String getName() { return this.name; } /** * @return Le nom avec la première lettre en majuscule... */ public String getFormattedName() { if (this.name.length()>=1) { return this.name.substring(0,1).toUpperCase() + this.name.substring(1); } return this.name; } }
Par contre la méthode getFormattedName() n'est pas thread-safe, car si un autre thread effectue un setName() pendant son déroulement, on peut se retrouver avec une valeur incorrect qui serait le mix des veux valeurs.
Par exemple si quand on rentre dans la méthode getFormattedName() :
- l'attribut name vaut "aaa", et le premier substring nous donne donc "a" puis "A".
- Un autre thread prend la main et change la valeur de l'attribut en "bbb"
- On reprend la main et on effectue le second substring qui donne "bb"
- :arrow: Au final on obtient "Abb" ce qui est totalement incorrect
A noter que cela pourrait être pire, car si on fait un setName("") on pourrait générer une exception sur le substring() car on aurait déjà passé le if() :?
C'est une solution. Dans mon exemple cela donnerait ceci :
:arrow: Désormais lorsqu'on exécute getFormattedName() on ne peut plus utiliser setName() depuis un autre thread, et inversement.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 class User { private String name; public synchronized void setName(String name) { this.name = name; } public String getName() { return this.name; } /** * @return Le nom avec la première lettre en majuscule... */ public synchronized String getFormattedName() { if (this.name.length()>=1) { return this.name.substring(0,1).toUpperCase() + this.name.substring(1); } return this.name; } }
Toutefois ce n'est pas forcément la meilleure solution, car c'est assez couteux (les threads sont endormis et doivent s'attendre mutuellement). Si dans certains cas on ne peut pas l'éviter, on peut généralement s'en passer (ou limiter la durée de la synchronisation) en travaillant avec des variables locales :
Par exemple :
:arrow: Désormais un setName() peut être effectué pendant getFormattedName() sans que cela ne provoque d'erreur ou de comportement incohérent ;)Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 class User { private String name; public void setName(String name) { this.name = name; } public String getName() { return this.name; } /** * @return Le nom avec la première lettre en majuscule... */ public synchronized String getFormattedName() { // On travaille sur une variable locale : String theName = this.name; if (theName.length()>=1) { return theName.substring(0,1).toUpperCase() + theName.substring(1); } return theName; } }
Bref : la notion de thread-safe consiste à faire un code sécurisé en cas d'utilisation depuis différents threads, souvent via un coût dû à la synchronisation.
a++
Je me suis trompé je voulais dire les ThreadLocal
c'est une variabe dont la valeur est différente pour chaque thread. Une des utilisations c'est de stocker dans la classe une valeur pour le thread courant pour la récupérer plus tard dans le traitement sans avoir à la passer en paramètre à toutes les méthodes. Une autre est de "marquer" le thread courant d'une information que tu devra reprendre dans le futur.
D'un point de vue "logique", une ThreadLocal est proche d'un Map<Thread,Object> qui serait synchronisé, mais en pratique c'est beaucoup plus performant car la donnée est stockée non pas dans ta classe mais dans le Thread sous la forme Map<ThreadLocal,Object> (donc pas besoin de synchronisation, mais attention à bien faire un set(null) quand t'en a plus besoin)