Java synchronisé liste pour la boucle

Documentation sur synchronizedList états,

Il est impératif que l'utilisateur de synchroniser manuellement sur la liste retournée lors de l'itération sur:

List list = Collections.synchronizedList(new ArrayList());
...
synchronized(list) {
    Iterator i = list.iterator(); // Must be in synchronized block
    while (i.hasNext())
    foo(i.next());
}

le fait de ne pas suivre ce conseil peut entraîner un comportement non déterministe.

Cela semble assez clair, mais je voulais juste confirmer que pour chaque boucle est interdite. Par exemple, je ne peux pas faire quelque chose comme comme suit juste?

List<MyType> list = Collections.synchronizedList(new ArrayList(<MyType>));
...
synchronized(list){
    for(MyType m : list){
        foo(m);
        m.doSomething();
    }
}
16
demandé sur user927476 2011-09-07 18:53:24

4 réponses

Oui, vous peut - optimisé pour la boucle est essentiellement la même que votre code qui utilise explicitement l'itérateur. Il se réduit au même code - il appelle juste iterator() et puis alternance entre next() et hasNext() appels.

27
répondu Jon Skeet 2011-09-07 14:56:03

Vous pouvez le faire. La boucle foreach compile (presque) le même bytecode que la boucle while. Les clés sont les suivantes:

  1. Vous synchronisez le bloc autour de la boucle, car la liste peut changer pendant que vous êtes à parcourir.
  2. vous utilisez la liste comme objet sur lequel vous synchronisez, puisque l'implémentation de cette classe se bloque sur elle-même (par des méthodes synchronisées).
1
répondu Ryan Gross 2011-09-07 14:56:51

bien sûr, vous pouvez, le seul problème que je vois ici est un problème de performances, si votre méthode dosomething() ou foo(m) coûteuses pour l'exécuter, vous aurez un coût de performance. La taille de votre collection est également importante à prendre en compte lors de la boucle dans un bloc synchronisé, en raison du fait que, lorsqu'un thread acquérir la serrure, alors que dans le bloc synchronisé, boucle dans une énorme collection poussera d'autres fils à attendre.

1
répondu Mike Njong 2017-03-23 21:24:08

Si possible, vous pouvez envisager d'utiliser l'immutabilité plutôt que de synchronisation.

http://docs.guava-libraries.googlecode.com/git-history/release09/javadoc/com/google/common/collect/ImmutableList.html

0
répondu John B 2011-09-07 15:05:17