Réponses:
Lorsque plusieurs threads doivent vérifier et modifier le booléen. Par exemple:
if (!initialized) {
initialize();
initialized = true;
}
Ce n'est pas thread-safe. Vous pouvez le corriger en utilisant AtomicBoolean
:
if (atomicInitialized.compareAndSet(false, true)) {
initialize();
}
true
quand initialize()
ils ne sont pas terminés. Donc, cela ne fonctionne que si les autres threads ne se soucient pas de l'achèvement de initialize()
.
initialized
est simplement utilisé pour garantir qu'un et un seul thread invoquera la initialize()
méthode. Évidemment, initialized
être vrai ne signifie pas que l'initialisation est définitivement terminée dans ce cas, donc peut - être qu'un terme légèrement différent serait mieux ici. Encore une fois, cela dépend de son utilisation.
volatile boolean
la même chose que AtomicBoolean
?.
synchronized
bloc, auquel cas vous n'avez plus besoin d'un AtomicBoolean
, juste d'un volatile boolean
. ( if(! this.initialized) { synchronized(this) { if(! this.initialized) { initialize(); this.initialized = true; } } }
garantira qu'un seul thread appelle initialize
et que tous les autres threads l'attendent, à condition que cela initialized
soit marqué volatile
.)
Voici les notes (du livre de Brian Goetz ) que j'ai prises, qui pourraient vous être utiles
Classes AtomicXXX
fournir une implémentation de comparaison et d'échange non bloquante
Profite de la prise en charge fournie par le matériel (l'instruction CMPXCHG sur Intel) Lorsque de nombreux threads s'exécutent dans votre code qui utilise ces API de concurrence atomique, ils évolueront bien mieux que le code qui utilise des moniteurs / synchronisation au niveau objet. Étant donné que les mécanismes de synchronisation de Java font attendre le code, lorsqu'il y a beaucoup de threads qui traversent vos sections critiques, une quantité substantielle de temps CPU est consacrée à la gestion du mécanisme de synchronisation lui-même (attente, notification, etc.). Étant donné que la nouvelle API utilise des constructions de niveau matériel (variables atomiques) et des algorithmes d'attente et de verrouillage gratuits pour implémenter la sécurité des threads, beaucoup plus de temps CPU est consacré à "faire des choses" plutôt qu'à gérer la synchronisation.
non seulement offrent un meilleur débit, mais ils offrent également une plus grande résistance aux problèmes de vivacité tels que l'impasse et l'inversion de priorité.
Il y a deux raisons principales pour lesquelles vous pouvez utiliser un booléen atomique. D'abord son mutable, vous pouvez le passer comme référence et changer la valeur associée au booléen lui-même, par exemple.
public final class MyThreadSafeClass{
private AtomicBoolean myBoolean = new AtomicBoolean(false);
private SomeThreadSafeObject someObject = new SomeThreadSafeObject();
public boolean doSomething(){
someObject.doSomeWork(myBoolean);
return myBoolean.get(); //will return true
}
}
et dans la classe someObject
public final class SomeThreadSafeObject{
public void doSomeWork(AtomicBoolean b){
b.set(true);
}
}
Plus important encore, son thread est sûr et peut indiquer aux développeurs qui maintiennent la classe que cette variable devrait être modifiée et lue à partir de plusieurs threads. Si vous n'utilisez pas un AtomicBoolean, vous devez synchroniser la variable booléenne que vous utilisez en la déclarant volatile ou en la synchronisant autour de la lecture et de l'écriture du champ.
La AtomicBoolean
classe vous donne une valeur booléenne que vous pouvez mettre à jour atomiquement. Utilisez-le lorsque plusieurs threads accèdent à une variable booléenne.
La vue d'ensemble du package java.util.concurrent.atomic vous donne une bonne description de haut niveau de ce que font les classes de ce package et quand les utiliser. Je recommanderais également le livre Java Concurrency in Practice de Brian Goetz.
Extrait de la description du package
Package java.util.concurrent.atomic description: Une petite boîte à outils de classes qui prennent en charge la programmation thread-safe sans verrouillage sur des variables uniques. [...]
Les spécifications de ces méthodes permettent aux implémentations d'employer des instructions atomiques efficaces au niveau de la machine qui sont disponibles sur les processeurs contemporains. [...]
Les instances des classes AtomicBoolean, AtomicInteger, AtomicLong et AtomicReference fournissent chacune un accès et des mises à jour à une seule variable du type correspondant. [...]
Les effets de mémoire pour les accès et les mises à jour atomiques suivent généralement les règles pour les volatiles:
- get a les effets de mémoire de la lecture d'une variable volatile.
- set a pour effet mémoire d'écrire (assigner) une variable volatile.
- faibleCompareAndSet lit atomiquement et écrit conditionnellement une variable, est ordonné par rapport aux autres opérations de mémoire sur cette variable, mais agit autrement comme une opération de mémoire non volatile ordinaire.
- compareAndSet et toutes les autres opérations de lecture et de mise à jour telles que getAndIncrement ont les effets de mémoire de la lecture et de l'écriture de variables volatiles.
volatile boolean
vsAtomicBoolean
: stackoverflow.com/questions/3786825/…