prostu ciekawi, w realizacji hashcode String, co jest powodem tworzenia dodatkowych referencje w realizacji hashcode (v 1.8.0_65):realizacja hashCode Java String
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
Biorąc pod uwagę, że value
jest ostateczna i stworzył tylko w konstruktorze (np. Threadafe), dlaczego potrzebujemy tutaj referencji zmiennej val []?
tj. to zadziała:
public int hashCode() {
if (hash == 0 && value.length > 0) {
int h = 0;
for (int i = 0; i < value.length; i++) {
h = 31 * h + value[i];
}
hash = h;
}
return hash;
}
?
Oprócz kopiowania wartości ze sterty do stosu, aby przyspieszyć, chodzi również o warunki wyścigu opisane w komentarzach @Zapl. Co nie było dla mnie oczywiste przed jego komentarzem.
Tu nie chodzi o unikanie getopt. Jest to http://jeremymanson.blogspot.de/2008/12/benign-data-races-in-java.html - wyścig danych, ponieważ 'hash' nie jest ani" zmienny ", ani nie jest synchronizowany. Dlatego nie "zwracają hash" (nie ma gwarancji co do wartości, którą czytasz). – zapl
Nie zgadzam się z tym stwierdzeniem. hash is int (not long), tj. wszystkie ops są atomowe, aw najgorszym przypadku po prostu obliczyć dwa razy, co może się zdarzyć w obu przypadkach. –
Nie chodzi o atomowe ustawianie wartości, ale o porządkowanie operacji (re). Od połączonego artykułu na temat twojej wersji: * To, co tutaj zrobiłem, to dodać dodatkowy odczyt: drugi odczyt skrótu przed powrotem. Dziwne, jak się wydaje, i tak mało prawdopodobne, jak to się stanie, pierwszy odczyt może zwrócić poprawnie obliczoną wartość skrótu, a drugi odczyt może zwrócić 0! Jest to dozwolone w modelu pamięci, ponieważ model umożliwia rozległą zmianę kolejności operacji. Drugi odczyt może zostać przeniesiony w twoim kodzie, tak aby twój procesor zrobił to przed pierwszym! * – zapl