Est-ce que java.util.concurrent.atomic.AtomicBoolean
ne possède pas une méthode qui peut inverser/inverser la valeur de manière atomique? Puis-je le faire d'une autre manière? Est-ce que je manque quelque chose?Est-ce que AtomicBoolean n'a pas de méthode negate()?
Répondre
Ma mise en œuvre naïve serait ceci:
boolean v;
do {
v=atomicBoolean.get();
} while(!atomicBoolean.compareAndSet(v, !v));
Les battements doivent se synchroniser :) – pjp
Non, ce n'est pas le cas parce que la bascule n'est pas atomique. La valeur de AtomicBoolean peut changer entre l'appel de get() et l'appel de compareAndSet() – skaffman
@skaffman: auquel cas le compareAndSet() échouera, retournera false et la boucle sera de nouveau entrée. Corrigez-moi si j'ai quelque chose de mal. –
peu vieux ... mais ne me sentais pas vraiment les réponses ont été formidables.
Je serais totalement en désaccord avec le fait que ce n'est pas commun ou seulement utile dans le matériel. Vous pouvez vouloir un certain nombre de threads pour basculer sur une seule variable avec la même probabilité ... J'ai utilisé l'AtomicLong pour faire un faux booléen. Cela a été adopté à partir d'un JMS MessageListener que j'avais besoin de répondre à un message particulier la moitié du temps et un autre type l'autre moitié.
public class Mock {
private static AtomicLong count = new AtomicLong(0);
public boolean respond() {
long currentCount = count.getAndIncrement();
if (currentCount % 2 == 0) {
return true;
} else {
return false;
}
}
}
En utilisant la méthode AtomicBoolean#compareAndSet() et une boucle while vous pouvez mettre en œuvre une méthode pour changer la valeur d'un AtomicBoolean d'une manière thread-safe comme ceci:
public static boolean negate(AtomicBoolean ab) {
// get the oposite value
boolean newVal = !ab.get();
// try to set the new value if the current value is the oposite of the new value
while (!ab.compareAndSet(!newVal, newVal)) {
// if the value we try to set was already set in the mean-time
// then toggle the new value and try again
newVal = !newVal;
}
// return the value we finally could set
return newVal;
}
@jtahlborn Je pense que vous avez tort. J'ai fait un test avec 50 threads simultanés essayant de basculer le AtomicBoolean 10.000 fois en attendant au hasard entre chaque itération pendant 0-5ms. Tous les threads terminés. Voulez-vous expliquer la situation dans laquelle vous pensez que cette méthode ne serait pas complète? La différence entre ma mise en œuvre et celle actuellement la mieux notée est que mine ne fait pas l'appel inutile et cher #get() dans chaque itération de la boucle while mais à la place il bascule la valeur locale et essaie ensuite de la définir. – sebthom
L'autre solution utilise la valeur actuelle pour avoir un choix légitime quant à la configuration.vous "devinez" que la nouvelle valeur devrait être le contraire. cela peut être vrai, cela peut être faux. "jamais terminé" n'était probablement pas une déclaration très précise. cependant, votre version "devine" à la valeur correcte (possibilité de succès plus rapide ou échec parasite), l'autre version utilise l'information courante pour choisir la valeur suivante (un autre appel avec une espérance de succès plus élevée). Je suppose que cela dépend du mode de fonctionnement que vous préférez. – jtahlborn
@jtahlborn Dans les versions de Nichola, le .get() et l'appel .compareAndSet() ne sont pas exécutés dans une seule opération atomique, ainsi la valeur de .get() peut déjà être obsolète au moment où .compareAndSet() est appelé, donc a la même probabilité d'être la bonne valeur que dans mon cas où je suis simplement en train de basculer la valeur locale et d'essayer à nouveau, ce qui donne une lecture volatile par itération. – sebthom
La solution proposée dans le livre The CERT Oracle Secure Coding Standard for Java est le suivant:
import java.util.concurrent.atomic.AtomicBoolean;
final class Flag {
private AtomicBoolean flag = new AtomicBoolean(true);
public void toggle() {
boolean temp;
do {
temp = flag.get();
} while(!flag.compareAndSet(temp, !temp));
}
}
- 1. Que signifie "méthode de classe #" dans ruby?
- 2. Que fait la méthode Container.validate()?
- 3. Que fait la méthode registerNatives()?
- 4. Méthode select select Méthode ORDER BY
- 5. CompositeData n'a pas de méthode keys()?
- 6. Expression régulière pour remplacer les champs délimités par des virgules vides par "NA"
- 7. Trigger-Méthode de WebControl n'est pas renvoyé
- 8. C++ méthode redéfinie pas appelé
- 9. Zend_Rest_Server n'invoque pas la méthode de classe
- 10. La méthode de jointure n'est pas implémentée
- 11. Pourquoi l'appel créé en tant que méthode de classe ne sauvegarde-t-il pas l'enregistrement?
- 12. Pourquoi le callback que je passe à la méthode animate() de jQuery n'est-il pas appelé?
- 13. méthode setNodeValue() ne fonctionne pas
- 14. Qu'est-ce que la méthode HOME?
- 15. Que va contenir la méthode XMLHttpRequest send?
- 16. Que signifie la méthode <ClassName>?
- 17. Une méthode de classe qui se comporte différemment lorsqu'elle est appelée en tant que méthode d'instance?
- 18. type anonyme en tant que paramètre de méthode
- 19. Qu'est-ce que c'est? Méthode de modèle ou quoi?
- 20. Les opérateurs en tant que paramètres de méthode en C#
- 21. La méthode de requête de l'association belongs_to n'existe pas
- 22. moq - comment vérifier que la méthode n'a pas été appelée si la classe avale les exceptions
- 23. Comment quitter Méthode Quand Ne pas utilisé cette méthode dans la méthode
- 24. Java: Les génériques ne fonctionneront pas pour ma méthode, que puis-je faire d'autre?
- 25. ASP.NET MVC Helper Extension Méthode ne rendant pas le texte en tant que contrôle
- 26. Quand est-ce que la méthode d'élimination ne serait pas appelée?
- 27. SFAuthorizationView autoriser: la méthode ne fonctionne pas
- 28. La méthode Javascript toSource() ne fonctionne pas
- 29. NSURLConnection n'appelle pas la méthode didRecieveData
- 30. Est-ce que self.class.delete appelle une méthode de classe?
Je ne comprends pas ce qui ne va pas avec booléen b = ab.get(); ab.compareAndSet (b,! b); Vous êtes assuré de retourner ce que vous avez dans le get. Est-il vraiment commun de vouloir retourner un booléen indépendamment de sa valeur actuelle à tout moment? – Yishai
@Yishai: Vous êtes assuré de retourner ce que vous avez dans le get, mais disons que vous aviez 'ab = true' et il y avait 2 togglers qui avaient une condition de course. Celui qui est arrivé là a d'abord basculé le morceau, et le second a dit "oh, j'ai déjà été basculé" et donc laissé seul. Cela laisserait 'ab = false', alors que si les opérations de bascule se produisaient séparément, cela laisserait' ab = true'. C'est un bug. Quant à savoir s'il est vraiment courant de basculer un booléen: C'est très courant dans le cas du matériel, pas sûr des situations purement logicielles. –
@Jason S, je pense que vous répétez comme une question positive, au moins dans le matériel (et donc la simulation de matériel si rien d'autre), vous auriez besoin de cela. Mais je ne sais pas si c'est suffisant pour une API, cependant. – Yishai