Disons que j'ai la classe suivante qui sera lu lourdement, mais seulement écrit à l'occasion. Il sera utilisé dans une application Web multi-threadé, il doit donc être le fil de sécurité:
public class Foo { private volatile String foo; public String getFoo() { return foo; } public synchronized String setFoo(String in) { this.foo = in; } }
3 Réponses :
Volatile Fournit un accès sans verrouillage de fil rapide à un champ sans synchronisation
private AtomicInteger id = new AtomicInteger(); public void incrementId() { return id.incrementAndGet(); }
Marquage d'une variable comme volatils ne le rend pas à fil sûr. Si tout le processus est en train de lire, c'est la lecture / l'écriture, il est efficacement sûr du fil (cela ne serait pas vrai si plusieurs threads incrémentent la variable de support ...).
Il y a donc une situation dans laquelle les deux volatiles et synchronisés seraient appropriés?
Je suis sûr qu'il n'y a pas de telle situation. Si vous synchronisez l'accès à un champ, volatile est redondant.
Pour peut-être clarifier un peu plus: si c'est un simple getter / setter, volittile va bien. Si, toutefois, vous utilisez la valeur existante de quelque manière que ce soit lors de la définition de la nouvelle valeur, vous devez utiliser une serrure (synchronisée). Notez que les opérations d'exécution sur les nouvelles données sont correctes: si SETFOO () définit FOO sur les 3 premiers caractères passés, utilisez un volitle. Si SetFoo () définit FOO sur le premier caractère de FOO, plus la nouvelle valeur, vous devez verrouiller.
Si tout ce que vous faites, c'est régler FOO, vous n'avez pas besoin de synchroniser la méthode. Faire de la référence volatile suffit. P>
Et si je fais plus dans la méthode du setter? Comme une opération de copie ou une opération de sous-chaîne. Serais-je juste synchroniser ou utiliser les deux?
Toute autre action dans le setter qui a besoin d'atomicité en ce qui concerne la valeur de la chaîne nécessitera une utilisation de la synchronisation, ce qui rendra le modificateur volatil inutile
@Owenberger - Si vous devez faire plus de travail dans le setter, vous devriez vous synchroniser. Cependant, la volatilité est toujours utile dans ce scénario car elle vous permet de ne pas synchroniser le getter (en supposant que vous ne vous souciez pas de si un appelant sur le getter obtient une valeur ancienne pendant qu'un autre appelant est dans le réglage).
au lien Vous avez dit là-bas Ce code pour "mises à jour peu fréquentes" Utilisation: L'incrément code> code> utilise uniquement synchronisé car il fait plus que définir la valeur de la valeur Code> Comme indiqué dans la description, si tout ce que vous faites est
this.foo = in; code> qui est atomique.
Dans le texte, la "fragilité de ce modèle" signifie que les choses peuvent être désordonnées très rapidement lorsque vous mélangez des méthodes de synchronisation volatiles et autres que de simples exemples simples.
Voir le package java.util.concurrent.locks pour les interfaces condition em> et verrouillage em> et la classe reentrantlock em>. Je pense que et utiliser synchronisé est ce que l'auteur signifie par "alternatives plus fortes". Vous devriez également voir objet.wait em>, objet.notifier em> et objet.notifyall em> si vous ne le savez pas encore. P> < / p>