2009-08-29 8 views
5

Dado el siguiente código:Ajuste seguro de subprocesos de una variable (Java)?

public class FooBar { 

public static volatile ConcurrentHashMap myConfigData = new ConcurrentHashMap();  

} 

public class UpdaterThread implements Runnable { 

run { 

//Query the Data from the DB and Update the FooBar config Data 
FooBar.myConfigData = ConfigDataDAO.getLatestConfigFromDB(); 
} 
} 

El Hilo Clase actualizará el myConfigData Membervariable regularmente (a través de un ejecutor cada 5 minutos). ¿La configuración de myConfigData en el subproceso "externo" es segura (atómica), o tengo que sincronizar cada operación de lectura y escritura con la variable myConfigData?

EDITAR: La pregunta no es si ConcurrentHashMap es enhebrable (está de acuerdo con javadoc) sino más bien la configuración del mismo ConcurrentHashMap en la variable miembro myConfigData. Esta variable puede leerse y escribirse "a la vez" por varios hilos, por lo que la pregunta es si la configuración es atómica o no. Creo que esto se puede generalizar a "¿La configuración de una variable de referencia Java es atómica o no?".

(también lo hice volátil Este es un tema diferente y no tiene nada que ver con la atomicidad - mi pregunta - sino más bien "visibilidad en otros hilos" y la relación sucede-antes..)

Respuesta

12

Reemplazar referencias es seguro. Ver Java language Specification:

Cuando un hilo utiliza el valor de una variable, el valor que obtiene de hecho es un valor almacenado en la variable por que el hilo o por algún otro hilo. Esto es cierto incluso si el programa no contiene código para una sincronización adecuada. Por ejemplo, si dos subprocesos almacenan referencias a objetos diferentes en el mismo valor de referencia, la variable contendrá posteriormente una referencia a un objeto u otro, no una referencia a algún otro objeto o un valor de referencia dañado. (Hay una excepción especial para los valores largos y dobles; ver §17.4.)

+3

@unknown: ¡el texto citado no dice lo que crees que dice! De hecho, la próxima viñeta en el JLS dice esto: "En ausencia de sincronización explícita, una implementación es gratuita para actualizar la memoria principal en un orden que puede ser sorprendente. Por lo tanto, el programador que prefiere evitar sorpresas debe usar sincronización explícita. " –

+1

@unknown: la única razón por la que el código del OP es seguro es que ha declarado la variable como 'volátil'. –

+3

@Stephen Creo que el punto principal de la pregunta fue sobre la atomicidad de la tarea. Es por eso que cité esta parte de la especificación. Si entiendo correctamente, esta atomicidad está garantizada incluso si no se utiliza volátil. Sin embargo, puede suceder que otros subprocesos nunca vean una actualización de la variable y sigan viendo la referencia "anterior". Sin embargo, un hilo nunca verá "una referencia a algún otro objeto o un valor de referencia dañado". – Wolfgang

0

ConcurrentHashMp es:

Una tabla hash que admite concurrencia completa de recuperaciones y concurrencia esperada ajustable para las actualizaciones. Esta clase obedece a la misma especificación funcional que Hashtable e incluye versiones de métodos correspondientes a cada método de Hashtable. Sin embargo, aunque todas las operaciones son seguras para subprocesos, las operaciones de recuperación no implican bloqueo, y no hay ningún soporte para bloquear toda la tabla de una manera que impida todo acceso. Esta clase es completamente interoperable con Hashtable en programas que confían en su seguridad de subprocesos pero no en sus detalles de sincronización.

Los javadocs dicen que es seguro para subprocesos.

Parece que hay mucho trabajo y ciclos de CPU para configurar la configuración. ¿Es realmente esta dinámica? ¿O cambias una vez al mes y solo necesitas un rebote de servicio cuando lo haces?

+0

Gracias por su respuesta! Traté de aclarar mi pregunta y edité mi pregunta. –

0

Si por actualización que decir sobrescribir una entrada dentro del ConcurrentHashMap:

FooBar.myConfigData.put(somekey, somevalue); 

entonces es definitivamente hilo de seguridad, como duffymo dijo.

Si desea sobrescribir la variable myConfigData con un nuevo valor:

FooBar.myConfigData = new ConcurrentHashMap(); 

También es seguro para subprocesos, como se ha etiquetado correctamente la variable como volátil. La palabra clave volatile significa que varios subprocesos pueden acceder a la misma variable de forma segura y atómica.

EDIT: La cuestión no es wether ConcurrentHashMap es multi-hilo (que es de acuerdo a javadoc), sino más bien la configuración de la propia ConcurrentHashMap en la variable myConfigData miembros. Esta variable puede leerse y escribirse "a la vez" por varios hilos, por lo que la pregunta es si la configuración es atómica o no. Creo que esto se puede generalizar, es la configuración de una variable de referencia de Java atómica o no.

(También lo volví volátil. Este es un problema diferente y no tiene nada que ver con la atomicidad (mi pregunta) sino más bien con "visibilidad en otros hilos" y lo que sucede antes de la relación).

realidad 'volátil' es de atomicidad, nada afecta a la visibilidad, una variable pública siempre será visible para cualquier tema.

+0

¡Muchas gracias por su respuesta! –

2

volatile garantiza atomicidad, visibilidad y actúa como una 'barrera de memoria' (google para ello, si quiere saber lo que eso significa) - al menos desde Java 5. Por lo tanto, hace exactamente lo que quiere.

0

Siempre puede usar AtomicReference si no está seguro.

Aunque creo que en su caso bastará con ser volátil.

Cuestiones relacionadas