Używam jody ze względu na jej dobrą opinię na temat wielowątkowości. Daje duże odległości, aby wielowątkowe przetwarzanie danych było wydajne, na przykład dzięki niezmienności wszystkich obiektów Date/Time/DateTime.Częściowo skonstruowany obiekt/wielowątkowość
Ale tutaj jest sytuacja, w której nie jestem pewien, czy Joda naprawdę robi dobrze. Prawdopodobnie tak, ale jestem bardzo zainteresowany, aby zobaczyć wyjaśnienie.
Kiedy toString() z DateTime jest nazywany Joda wykonuje następujące operacje:
/* org.joda.time.base.AbstractInstant */
public String toString() {
return ISODateTimeFormat.dateTime().print(this);
}
Wszystkie formatujących są bezpieczne dla wątków (one niezmienne, jak również), ale co o formatyzatora-przetwórni:
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;
}
Jest to popularny wzór w aplikacjach z jednym gwintem, ale wiadomo, że jest podatny na błędy w środowisku wielowątkowym.
widzę następujące zagrożenia: stan
- Race podczas sprawdzania null -> najgorszy przypadek: dwa przedmioty dostać utworzony.
Nie ma problemu, ponieważ jest to wyłącznie obiekt pomocniczy (w przeciwieństwie do normalnej sytuacji pojedynczego wzoru), jeden zostaje zapisany w dt, drugi zostaje utracony i prędzej czy później zostanie zebrany śmieci.
- zmienna statyczna może wskazywać na częściowo wybudowanego obiektu przed objec została zakończona inicjalizacja
(przed wywołaniem mnie do szału, przeczytaj o podobnej sytuacji w tym Wikipedia article.)
Tak w jaki sposób Joda zapewnia, że żaden częściowo utworzony formatter nie zostanie opublikowany w tej zmiennej statycznej?
Dzięki za wyjaśnienia!
Reto
+1. to kolejny powód, dla którego obiekty niezmienne są "prostsze" w równoległym modelu Java. Jednak nie jestem pewien o swoim ostatnim akapicie, patrz JLS 17.4.4: „Wpisanie wartości domyślnej (zero, fałszywe lub null), aby każda zmienna synchronizuje-z pierwszej akcji w każdym wątku”. Konieczne jest, aby "zapis wartości domyślnej" nastąpił przed odczytaniem dt. – irreputable
Tak, zapis wartości domyślnej jest przed odczytem dt. Zapobiega to wątkom odczytywania wartości "śmieci". Ale zapis pola w innym wątku (który zainicjował pole dt) nie jest w relacji hb z odczytanym dt. W ten sposób możemy zobaczyć dowolny z tych dwóch zapisów (domyślnie lub z wątku, który zainicjował dt) w dowolnym momencie. Jedynym momentem, w którym musimy odczytać domyślną wartość inicjalizacji, jest sprawdzenie wymaganej ilości. Ale w tym czasie możemy popełnić tylko jeden odczyt o wartości domyślnej i na następnej iteracji powiedzieć, że wątek zobaczyć zapis obiektu DT (tylko dla pierwszego odczytu w metodzie). – maxkar