Estoy usando joda debido a su buena reputación con respecto al multi threading. Recorre grandes distancias para hacer que el manejo de la fecha de múltiples hilos sea eficiente, por ejemplo, haciendo que todos los objetos de Fecha/Hora/Fecha y Hora sean inmutables.Objeto parcialmente construido/Multi threading
Pero aquí hay una situación en la que no estoy seguro de si Joda realmente está haciendo lo correcto. Probablemente sí, pero estoy muy interesado en ver una explicación.
Cuando un toString() de un DateTime se está llamando Joda hace lo siguiente:
/* org.joda.time.base.AbstractInstant */
public String toString() {
return ISODateTimeFormat.dateTime().print(this);
}
Todos los formateadores son seguros para subprocesos (que inmutables también), pero lo que está sobre el formateador de fábrica:
private static DateTimeFormatter dt;
/* org.joda.time.format.ISODateTimeFormat */
public static DateTimeFormatter dateTime() {
if (dt == null) {
dt = new DateTimeFormatterBuilder()
.append(date())
.append(tTime())
.toFormatter();
}
return dt;
}
Este es un patrón común en aplicaciones de subproceso único, pero se sabe que es propenso a errores en un entorno multiproceso.
veo los siguientes riesgos: condición
- Carrera durante el check nula -> peor de los casos: dos objetos se crean.
No hay problema, ya que esto es únicamente un objeto auxiliar (a diferencia de una situación normal patrón singleton), uno se guardan en dt, el otro está perdido y habrá basura recogida tarde o temprano.
- la variable estática podría apuntar a un objeto construido parcialmente antes de la objec se ha terminado la inicialización
(antes de llamar loco, leer acerca de una situación similar en este Wikipedia article.)
Así ¿Cómo se asegura Joda de que ningún formateador creado parcialmente se publique en esta variable estática?
¡Gracias por sus explicaciones!
Reto
+1. esa es otra razón por la cual los objetos inmutables son 'más simples' en el modelo concurrente de Java. Sin embargo, no estoy seguro acerca de su último párrafo, consulte JLS 17.4.4: "La escritura del valor predeterminado (cero, falso o nulo) para cada variable se sincroniza, con la primera acción en cada hilo". Es necesario que la "escritura del valor predeterminado" ocurra antes de la lectura de dt. – irreputable
Sí, una escritura de valor predeterminado es anterior a la lectura de dt. Esto evita que el hilo lea el valor de "basura". Pero una escritura del campo en otro hilo (que inicializó el campo dt) no está en relación hb con la lectura dt. Por lo tanto, podemos ver cualquiera de esas dos escrituras (por defecto o desde un hilo que inicializó dt) en cualquier momento. El único momento en que debemos leer un valor de inicialización predeterminado es verificar el requisito de casualidad. Pero en ese momento solo cometemos una sola lectura con el valor predeterminado y en la siguiente iteración, dicho, esa secuencia ve una escritura de un objeto para dt (solo para la primera lectura en el método). – maxkar