2012-09-03 12 views
14

Hasta donde yo sé, java.util.Date es mutable, por lo que no es seguro para subprocesos si varios subprocesos intentaron acceder y modificarlo. ¿Cómo utilizamos el bloqueo o la composición del lado del cliente (envoltorio) para que sea seguro para subprocesos?Cómo hacer que Java.util.Date sea seguro para subprocesos

+4

Si ya estamos aquí, 'GregorianCalendar' y' SimpleDateFormat' tampoco son seguros para subprocesos. Siempre vale la pena recordar. –

+0

Gracias por recordar – peter

Respuesta

28

En este orden, de mejor a peor:

  1. lo uso para nada, echa un vistazo a

  2. lo utilice en absoluto, usar AtomicLong o inmutable primitiva long con volatile para representar epoch time

  3. Encapsularlo. Siempre devuelva una copia defensiva de Date, nunca una referencia al objeto interno

  4. Sincronizar en Date instancia.

+0

Me pregunto por qué consideraste que el segundo es mejor que el tercero? – peter

+2

@ user1389813: ¡Buena pregunta! 1. Los primitivos son inmutables y, por lo tanto, implícitamente son seguros para subprocesos. 2. No puede, por coincidencia, devolver la referencia al objeto interno en lugar de una copia defensiva. 3. Más liviano, menos copiado (no es realmente un gran problema). Sin embargo, estoy de acuerdo, 2 y 3 son ambos bastante buenos. También obviamente 'Fecha' tiene mejor semántica que' largo'. –

+0

Ya veo. El 2do punto que necesita el guardia con un candado ¿verdad? como @dystroy señaló que la operación de incremento no es atómica. – peter

-1

No existe una solución simple para crear un contenedor seguro para subprocesos de la clase Date. La mejor manera es sincronizar todos los usos de sus objetos usando los bloques synchronized.

+0

Luego necesita llevar ese bloque de sincronización donde quiera que lo use. ¿No es bueno en la práctica? – peter

+0

Es horrible en el código. Esta es la razón por la que la respuesta de Tomasz es mucho mejor que la mía;) –

2

La solución más simple es nunca modificar una fecha y nunca compartirla. es decir, solo use la fecha para las variables locales.

Puede usar JodaTime ya que tiene objetos de fecha inmutables.

3

Puede usar el valor largo (milisegundos desde Época) en lugar de una instancia de Fecha. Asignarlo será una operación atómica y siempre será coherente.

Pero quizás su problema no esté en el valor de la fecha en sí, sino en todo el algoritmo, lo que significa que la respuesta real estaría basada en su problema real.

Aquí está un ejemplo de funcionamiento con errores en un contexto multi-hilo:

long time; 
void add(long duration) { 
    time += duration; 
} 

El problema aquí es que es posible que tenga dos adiciones en paralelo lo que resulta en una sola adición efectiva, porque time += duration no es atómica (que es realmente time=time+duration).

No es suficiente usar un objeto largo en lugar de mutable. En este caso, podría resolver el problema configurando la función como sincronizada, pero otros casos podrían ser más complicados.

+0

¿Qué quiere decir con 'su problema tal vez no está en el valor de los datos en sí, sino en todo el algoritmo – peter

+0

Si' Estamos haciendo una operación larga comenzando por leer la fecha y terminar reemplazando el valor. Bloquear el valor durante la operación podría hacerlo. –

+0

¿Ayudará si se convierte en volátil? – peter

Cuestiones relacionadas