2011-09-07 14 views
15

Documentación sobre synchronizedList establece que,Java lista sincronizada de bucle

Es imperativo que el usuario sincronizar manualmente en la lista devuelta cuando se itera sobre ella:

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

no seguir este consejo puede dar como resultado un comportamiento no determinista.

Esto parece bastante claro, pero solo quería confirmar que se prohíbe una para cada ciclo. Por ejemplo, no puedo hacer algo como lo siguiente ¿no?

List<MyType> list = Collections.synchronizedList(new ArrayList(<MyType>)); 
... 
synchronized(list){ 
    for(MyType m : list){ 
     foo(m); 
     m.doSomething(); 
    } 
} 
+4

¿Por qué estaría prohibido? El bytecode generado es prácticamente el mismo. Foreach usa el iterador ... –

+0

Parece que synchronizedList solo decora las llamadas al método con sincronización, pero tiene limitaciones. Tal vez los diseñadores deberían haber decorado el método del iterador también, y devolver un iterador sincronizado. El texto está en el idioma y no se puede decorar tan fácilmente XD: –

Respuesta

26

Sí, puede - su bucle forzado es básicamente el mismo que su código que utiliza explícitamente el iterador. Se reduce al mismo código: simplemente llama al iterator() y luego alterna entre next() y hasNext() llamadas.

+0

si eliminamos elementos del iterador, mientras usamos hasNext()/next() está bien. pero si eliminamos algún elemento de la lista cuando lo repetimos por for (int: list) loop - arrojará ConcurentModificationException. Entonces no es lo mismo en este contexto. – ses

+0

@ses: Pero el código proporcionado no usa 'remove'. Un bucle for mejorado utiliza el iterador (para los que no son arrays), pero eso no significa que pueda hacer todo lo posible con un bucle for mejorado que podría hacer directamente con el iterador. –

+0

Eso es ... ¿Podrían ver mi pregunta aquí: http://stackoverflow.com/questions/16742763/using-iterator-over-for-loop-in-concurrent-java-app – ses

1

Usted puede hacer eso. El bucle foreach compila (casi) el mismo bytecode que el bucle while. Las claves son:

  1. Se sincroniza el bloque alrededor del bucle porque la lista puede cambiar mientras se itera sobre ella.
  2. Utiliza la lista como el objeto sobre el que está sincronizando, ya que la implementación de esta clase se bloquea sobre sí misma (a través de métodos sincronizados).
1

Por supuesto que puedes, el único problema que veo aquí es un problema de rendimiento, si su método dosomething() o foo(m) son costosos para ejecutar, tendrá un costo de rendimiento. También es importante tener en cuenta el tamaño de tu colección mientras bucleas en un bloque sincronizado, debido al hecho de que, cuando un hilo adquiere el bloqueo, mientras está en el bloque sincronizado, el bucle en una gran colección empujará a otros hilos a esperar.

+0

Algunos formatos, algunas palabras más y en realidad podría ser una respuesta;] – t3chb0t

Cuestiones relacionadas