2009-07-29 8 views
1

Dans le livre Java Servlet Programming, il y a un exemple de servlet à la page 54 qui recherche les nombres premiers dans un fil d'arrière-plan. Chaque fois qu'un client accède au servlet, le nombre premier le plus récemment trouvé est renvoyé.Une variable accessible par plusieurs threads dans une servlet Java doit-elle être déclarée volatile?

La variable qui est utilisée pour stocker le plus récemment trouvé le premier est déclaré comme tel:

long lastprime = 0; 

Comme cette variable est begin accessible à partir de plusieurs threads (le fil d'arrière-plan qui est de faire les calculs et les discussions des clients qui y accéder), n'a-t-il pas besoin d'être déclaré volatile ou avoir son accès synchronisé d'une manière ou d'une autre?

Répondre

8

Oui, en supposant que vous souhaitiez vraiment voir le nombre premier le plus récemment calculé sur n'importe quel thread, il doit être volatile ou être accessible de manière thread-safe via synchronized blocs/méthodes. De plus, comme indiqué dans les commentaires, les variables longues non volatiles peuvent ne pas être mises à jour de manière atomique - vous pouvez donc voir les 32 premiers bits d'une ancienne valeur et les 32 derniers bits d'une nouvelle valeur (ou vice versa). J'ai oublié le côté de l'atomicité des choses plus tôt car il est presque toujours résolu lorsque vous vous assurez d'obtenir la dernière valeur publiée, et assurez-vous de publier toutes les nouvelles valeurs. En pratique, c'est presque toujours ce que vous voulez, donc l'atomicité devient un non-problème si votre code fonctionne correctement pour commencer.

Ce n'est pas une servlet SingleThreadModel est-ce? Cela ferait évidemment une différence. Une autre alternative aurait été d'utiliser AtomicLong.

+1

Je voterais pour AtomicLong –

+0

Non, ce n'est pas un servlet SingleThreadModel. C'est un exemple d'utilisation d'une servlet pour effectuer un traitement en arrière-plan. – MCS

+0

On dirait que c'est juste un mauvais exemple alors. Il arrive - les auteurs ne savent jamais ce dont ils parlent;) –

1

Oui. Les variables d'un servlet ne sont pas thread-safe.

1

Il existe une séparation propre en lecture/écriture entre les threads; un thread "publie" le dernier premier pour que d'autres le lisent, alors vous pouvez vous en sortir en le rendant volatile.

Si le modèle d'accès impliquait des séquences de lecture-modification-écriture ou similaires, vous devrez synchroniser l'accès au champ.

1

En supposant Java 5 ou plus tard, le déclarer volatile donne une sémantique bien définie telle que here dessiné. Sur le principe de supprimer le doute de l'esprit du mainteneur de code j'utiliserais volatile, en disant "oui je sais que plusieurs threads utilisent cette variable".

La question interessante est l'effet de ne pas la déclarer volatile. Pourvu que vous avez un prime, est-ce important si c'est le dernier disponible? Volatile assure que les valeurs sont prises de la mémoire, pas de caches "CPU", donc vous devriez obtenir une valeur plus à jour.

Qu'en est-il de la possibilité de voir un assigment partiel? Pourriez-vous obtenir vraiment malchanceux et voir un long dont les LSB font partie d'une ancienne valeur et les MSB font partie d'une valeur différente? Eh bien, les affectations aux longs et aux doubles ne sont pas atomiques, donc en théorie oui! Ergo, volatil ou synchronisé n'est pas seulement un produit agréable à ...vous en avez besoin

0

Sémantique de variables volatiles en Java ne sont pas assez forts pour faire l'opération d'augmentation (de lastprime ++) atomique, à moins que vous pouvez garantir que la variable est écrite uniquement à partir d'un seul fil - pas dans le cas de servlet

D'un autre côté, l'utilisation de variables AtomicXXX est sûre pour les threads, tant qu'aucune opération composée n'est effectuée. Il y aura une fenêtre de vulnérabilité lors de la mise à jour de plus d'une variable atomique, même si chaque appel est atomique.

Questions connexes