8
votes

Synchroniser l'accès à l'écriture à un champ volatil (bloc de lecture de lecture bon marché)

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;
    }
}


0 commentaires

3 Réponses :


15
votes

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();
 }


4 commentaires

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.



2
votes

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.


3 commentaires

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).



2
votes

au lien Vous avez dit là-bas Ce code pour "mises à jour peu fréquentes" Utilisation: xxx

L'incrément utilise uniquement synchronisé car il fait plus que définir la valeur de la valeur Comme indiqué dans la description, si tout ce que vous faites est this.foo = in; 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 et verrouillage et la classe reentrantlock . Je pense que et utiliser synchronisé est ce que l'auteur signifie par "alternatives plus fortes". Vous devriez également voir objet.wait , objet.notifier et objet.notifyall si vous ne le savez pas encore. < / p>


0 commentaires