2010-02-22 5 views
4

ai-je besoin de synchroniser ceci, quand de nombreux threads accèdent à la méthode get et qu'un seul thread accède à la méthode setList? Je ne m'inquiète pas si les lecteurs obtiennent des données anciennes, mais les données doivent être cohérentes.Beaucoup de lecteurs, un écrivain: Ai-je besoin de synchroniser cela?

Janning

+1

Qu'est-ce que votre computeList() faire? Cela dépend-il de myList? – Uri

+0

non, désolé de ne pas le mentionner – Janning

Répondre

5

Vous ne devez pas synchroniser (mais vous devez déclarer myList comme volatile) si les conditions suivantes sont remplies:

  • computeList ne dépend pas de l'état actuel de myList
  • Vous ne modifiez pas le contenu de la liste après son affectation (Collections.unmodifiableList(computeList()) est le meilleur moyen d'exprimer cette condition)
+2

+1 pour unmodifiableList – Poindexter

+0

grand merci à la fois! La deuxième réponse était légèrement meilleure :-) – Janning

1

Non, vous n'avez pas besoin de synchronisation. Il n'y a pas de modifications simultanées (si computeList() ne dépend pas du myList).

btw, pourquoi renvoyez-vous new ArrayList(myList) au lieu de simplement retourner myList?

+2

@splix Probablement parce qu'il ne veut pas que sa liste soit modifiée par un client en dehors de la classe. Renvoyer 'myList' exposerait une référence à la liste, ainsi le client serait capable de le changer comme il veut. Et _that_ serait un bug de simultanéité classique ... –

+0

vous avez raison, retourner la liste doit être thread-safe, aussi. – Janning

0

Peu importe que computeList dépende de myList ou non, tant qu'il n'y a qu'un accès en lecture au contenu de myList, aucun problème de synchronisation ne peut survenir.

Si vous n'utilisez pas volatile pour myList, il se peut que get retourne l'ancienne myList, même si elle a déjà été remplacée par la liste. Si cela ne vous dérange pas (cela peut mener à deux threads voyant des valeurs différentes), alors vous n'avez pas besoin de volatile.

0

je préférerais faire la copie implicite

public class ListContainer { 

    private final List<String> myList = new CopyOnWriteArrayList<String>(); 

    public List<String> get(){ 
     return myList; 
    } 

    public List<String> set(){ 
     computeList(); 
    } 
} 

HTH