decir que tengo un objeto de datos:grupo de subprocesos, datos compartidos, Sincronización Java
class ValueRef { double value; }
donde cada objeto de datos se almacena en una colección maestra:
Collection<ValueRef> masterList = ...;
también tener una colección de trabajos, donde cada trabajo tiene una colección local de objetos de datos (donde cada objeto de datos también aparece en el masterList
):
class Job implements Runnable {
Collection<ValueRef> neededValues = ...;
void run() {
double sum = 0;
for (ValueRef x: neededValues) sum += x;
System.out.println(sum);
}
}
de casos de uso:
for (ValueRef x: masterList) { x.value = Math.random(); }
rellenar una cola de trabajos con algunos puestos de trabajo.
despertar a un grupo de subprocesos
Esperar a que cada puesto de trabajo se ha evaluado
Nota: Durante la evaluación del trabajo, todos los valores son todos constantes. Sin embargo, los subprocesos posiblemente hayan evaluado trabajos en el pasado y conserven valores en caché.
Pregunta: ¿Cuál es la cantidad mínima de sincronización necesaria para garantizar que cada thread vea los últimos valores?
Entiendo la sincronización desde el monitor/lock-perspective, no entiendo sincronizar desde el cache/flush-perspective (es decir, qué está garantizado por el modelo de memoria al entrar/salir del bloque sincronizado).
Para mí, parece que debería sincronizar una vez en el hilo que actualiza los valores para asignar los nuevos valores a la memoria principal y una vez por hilo de trabajo para vaciar la caché para que se lean los nuevos valores. Pero no estoy seguro de cómo hacer esto.
Mi enfoque: crear un monitor mundial: static Object guard = new Object();
A continuación, sincronizar el guard
, mientras que la actualización de la lista maestra. Finalmente, antes de iniciar el grupo de subprocesos, una vez para cada subproceso del grupo, sincronice en guard
en un bloque vacío.
¿Eso realmente causa una descarga total de cualquier valor leído por ese hilo? ¿O solo los valores tocados dentro del bloque de sincronización? En cuyo caso, en lugar de un bloque vacío, ¿debería leer cada valor una vez en un ciclo?
Gracias por su tiempo.
Editar: Creo que mi cuestión se reduce a, una vez que sale de un bloque sincronizado, no todos los primeros de lectura (después de ese punto) ir a la memoria principal? Independientemente de en qué sincronicé?
Parece casi un lugar perfecto para tomar ventaja de la palabra clave volátil – ControlAltDel
Escribo una vez (efectivamente constante), pero puedo leer millones de veces. Volátil nunca se almacena en la memoria caché localmente. Si crease el grupo de subprocesos cada vez, el código funcionaría bien sin sincronización/volátil (ya que no existiría el caché anterior). –
No veo la necesidad de volátiles aquí. Si ValueRef es efectivamente inmutable, solo hazlo realmente inmutable. Use doble. Cree una nueva colección para cada trabajo antes de programarla y envuélvala en Colección no modificable (solo como recordatorio). ¿Qué problema tienes? –