J'ai lu " Quand utiliser 'volatile' en Java? " Mais je suis toujours confus. Comment savoir quand je devrais marquer une variable volatile? Que se passe-t-il si je me trompe, soit en omettant une valeur volatile sur quelque chose qui en a besoin, soit en mettant une valeur volatile sur quelque chose qui n'en a pas? Quelles sont les règles à suivre pour déterminer quelles variables doivent être volatiles dans du code multithread?
- Jamais utiliser le mot clé volatile en Java ? (5 réponses )
- A quoi sert le mot clé "volatile"? (5 réponses )
Réponses
Trop de publicités?En gros, vous l'utiliser lorsque vous voulez laisser un membre de la variable soit accessible par plusieurs threads, mais n'ont pas besoin composé atomicité (pas sûr si c'est la bonne terminologie).
class BadExample {
private volatile int counter;
public void hit(){
/* This operation is in fact two operations:
* 1) int tmp = this.counter;
* 2) this.counter = tmp + 1;
* and is thus broken (counter becomes fewer
* than the accurate amount).
*/
counter++;
}
}
le ci-dessus est un mauvais exemple, parce que vous devez composé de l'atomicité.
class BadExampleFixed {
private int counter;
public synchronized void hit(){
/*
* Only one thread performs action (1), (2) at a time
* "atomically", in the sense that other threads can not
* observe the intermediate state between (1) and (2).
* Therefore, the counter will be accurate.
*/
counter++;
}
}
Maintenant un exemple:
class GoodExample {
private static volatile int temperature;
//Called by some other thread than main
public static void todaysTemperature(int temp){
// This operation is a single operation, so you
// do not need compound atomicity
temperature = temp;
}
public static void main(String[] args) throws Exception{
while(true){
Thread.sleep(2000);
System.out.println("Today's temperature is "+temperature);
}
}
}
Maintenant, pourquoi ne pouvez-vous pas simplement utiliser private static int temperature
? En fait, vous pouvez (dans le sens que votre programme ne sera pas sauter ou quelque chose), mais le changement d' temperature
par l'autre thread peut ou ne peut pas être "visible" pour le thread principal.
Fondamentalement, cela signifie qu'il est même possible que votre application. continue a écrire Today's temperature is 0
toujours si vous n'avez pas utiliser volatile
(dans la pratique, la valeur tend à devenir finalement visible. Cependant, vous ne devez pas risquer de ne pas utiliser volatile lorsque cela est nécessaire, car elle peut conduire à de méchants bugs (causés par la entièrement construit des objets, etc.).
Si vous mettez de l' volatile
mot clé sur quelque chose qui n'a pas besoin d' volatile
, cela n'affectera pas votre code de justesse (c'est à dire le comportement ne changera pas). En termes de performances, il dépendra de la JVM. En théorie, vous pourriez obtenir une petite dégradation des performances, car le compilateur ne peut pas faire la réorganisation des optimisations ont pour invalider le cache du PROCESSEUR, etc., mais là encore, le compilateur pourrait prouver que votre domaine ne peut jamais être accédé par plusieurs threads et supprimer l'effet de l' volatile
mot-clé complètement et de le compiler les mêmes instructions.
EDIT:
Répondre à ce commentaire:
Ok, mais pourquoi ne pouvons-nous pas faire todaysTemperature de synchronisation et de créer en parallèle, un getter pour la température?
Vous pouvez et il va se comporter correctement. Tout ce que vous pouvez avec volatile
peut être fait avec synchronized
, mais pas vice-versa. Il y a deux raisons pour lesquelles vous pourriez préférer volatile
si vous le pouvez:
- Moins de bug source d'erreurs: Cela dépend du contexte, mais dans de nombreux cas, l'aide d'
volatile
est moins sujettes à la simultanéité des bugs, comme le blocage tout en maintenant le verrou, les blocages, etc. - Plus performant: Dans la plupart des JVM implémentations,
volatile
peut avoir considérablement d'un débit plus élevé et un meilleur temps de réponse. Cependant, dans la plupart des applications, la différence est trop petite à la matière.
Volatile qui est le plus utile dans les algorithmes sans verrouillage. Vous marquez la variable contenant des données partagées, alors que la volatilité lorsque vous n'êtes pas en utilisant le verrouillage d'accès à cette variable et que vous voulez les modifications apportées par un thread pour être visible dans un autre, ou vous souhaitez créer un "arrive-après" rapport pour s'assurer que le calcul n'est pas re-commandé, encore une fois, pour s'assurer que les changements deviennent visibles au moment opportun.
Le JMM livre de cuisine décrit les opérations qui peuvent être re-commandé et qui ne le peuvent pas.
Les volatile
peuvent également être utilisés pour publier en toute sécurité des objets immuables dans un environnement multithread.
La déclaration d'un champ tel que public volatile ImmutableObject foo
garantit que tous les threads voient toujours la référence d'instance actuellement disponible.
Voir Concurrence Java en pratique pour plus d'informations à ce sujet.
http://mindprod.com/jgloss/volatile.html
"Le mot clé volatile est utilisé sur des variables pouvant être modifiées simultanément par d'autres threads."
"Etant donné que les autres threads ne peuvent pas voir les variables locales, il n’est jamais nécessaire de marquer les variables locales comme volatiles. Vous avez besoin de synchroniser pour coordonner les modifications apportées aux variables de différents threads, mais souvent volatile est suffisant pour les examiner."