En Java, ¿debo declarar que mi colección está sincronizada si es de solo lectura?
-
02-07-2019 - |
Pregunta
Lleno una colección una sola vez cuando se inicia mi aplicación web J2EE. Luego, varios hilos pueden acceder al mismo tiempo pero solo para leerlo.
Sé que usar una colección sincronizada es obligatorio para la escritura paralela, pero ¿todavía la necesito para la lectura paralela?
Solución
Normalmente no, porque en este caso no está cambiando el estado interno de la colección. Cuando recorres la colección, se crea una nueva instancia del iterador y el estado de la iteración es por instancia del iterador.
Nota aparte: recuerde que al mantener una colección de solo lectura, solo está evitando modificaciones a la colección en sí. Cada elemento de colección aún es cambiable.
class Test {
public Test(final int a, final int b) {
this.a = a;
this.b = b;
}
public int a;
public int b;
}
public class Main {
public static void main(String[] args) throws Exception {
List<Test> values = new ArrayList<Test>(2);
values.add(new Test(1, 2));
values.add(new Test(3, 4));
List<Test> readOnly = Collections.unmodifiableList(values);
for (Test t : readOnly) {
t.a = 5;
}
for (Test t : values) {
System.out.println(t.a);
}
}
}
Esto produce:
5
5
Consideraciones importantes del contestador @WMR.
Depende de si los hilos que están Se inicia la lectura de tu colección. Antes o después de que lo estés llenando. Si se inician antes de que lo llenes, no tiene garantías (sin sincronizando), que estos hilos Alguna vez verá los valores actualizados.
La razón de esto es la memoria de Java Modelo, si quieres saber más lee el sección " Visibilidad " en este enlace: http://gee.cs.oswego.edu/dl/cpj/jmm. html
E incluso si se inician los hilos Después de llenar su colección, usted podría tener que sincronizar porque su la implementación de la colección podría cambiar su estado interno incluso en lectura operaciones (gracias Michael Bar-Sinaí , No conocía tales colecciones existido).
Otra lectura muy interesante en el tema de concurrencia que cubre temas como la publicación de objetos, Visibilidad, etc. con mucho más detalle. es el libro de Brian Goetz Java Concurrencia en Practica .
Otros consejos
Depende de si los subprocesos que leen tu colección se inician antes o después de completarlo. Si se inician antes de llenarlo, no tiene garantías (sin sincronización) de que estos subprocesos verán los valores actualizados.
El motivo de esto es el modelo de memoria Java, si quieres saber más, lee la sección " Visibilidad " en este enlace: http://gee.cs.oswego.edu/dl/ cpj / jmm.html
E incluso si los subprocesos se inician después de llenar su colección, es posible que tenga que sincronizar porque la implementación de la colección podría cambiar su estado interno incluso en las operaciones de lectura (gracias Michael Bar-Sinai , no conocía tales colecciones existía en el estándar JDK).
Otra lectura muy interesante sobre el tema de la concurrencia que cubre temas como la publicación de objetos, la visibilidad, etc. con mucho más detalle es el libro de Brian Goetz Java Concurrency in Practice .
En el caso general, deberías. Esto se debe a que algunas colecciones cambian su estructura interna durante las lecturas. Un LinkedHashMap que usa orden de acceso es un buen ejemplo. Pero no solo tome mi palabra por ella:
En los mapas hash vinculados ordenados por el acceso, solo consultar el mapa con get es una modificación estructural javadoc del mapa de hash vinculado
Si está absolutamente seguro de que no hay cachés, estadísticas de recopilación, optimizaciones ni cosas divertidas, no necesita sincronizar. En ese caso, habría puesto una restricción de tipo en la colección: no declarar la colección como un Mapa (que permitiría LinkedHashMap) sino como HashMap (para los puristas, una subclase final de HashMap, pero eso podría estar tomando demasiado) lejos ...).
No tiene que hacerlo, como se explica en otras respuestas. Si desea asegurarse de que su colección es de solo lectura, puede utilizar:
yourCollection = Collections.unmodifableCollection(yourCollection);
(existe un método similar para Lista, Conjunto, Mapa y otros tipos de colección)
La colección en sí no lo hace, pero tenga en cuenta que si lo que contiene no es inmutable también, esas clases separadas necesitan su propia sincronización.