2017-04-27 3 views
10

Mit Blick auf Javas String Klasse können wir sehen, dass Hash-Code nach der ersten Auswertung zwischengespeichert wird.Java String Hashcode Caching-Mechanismus

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; 
} 

Wo hash eine Instanzvariable ist. Ich habe eine Frage, warum brauchen wir die h zusätzliche Variable?

+1

Es ist so geschrieben, um sicherzustellen, dass die "String" -Klasse Thread-sicher ist. Sie können mehr über dieses Konzept [hier] lesen (https://en.wikipedia.org/wiki/Thread_safety) – Valy

+1

Dieser Wikipedia-Link erklärt nicht vollständig, was hier vor sich geht oder warum. –

Antwort

5

Einfach weil hash Wert in der Schleife ändert und Ihre Lösung ohne temporäre Zwischenvariable nicht Thread-sicher ist. Beachten Sie, dass diese Methode in mehreren Threads aufgerufen wird.

Say thread-1 gestartet hash Berechnung und es ist nicht mehr 0. Einige kleine Momente später thread-2 ruft die gleiche Methode hashCode() auf das gleiche Objekt und sieht, dass hash ist nicht 0, aber thread-1 hat noch nicht ihre Berechnung abgeschlossen. Als Ergebnis wird in thread-2 falscher hash (nicht vollständig berechnet) Wert verwendet.

3

Es ist ein einfacher und billiger Synchronisationsmechanismus.

Wenn ein Thread hashCode() zum ersten Mal aufruft, und ein zweiter Thread ruft es wieder, während der erste Thread den Hash zu berechnen, würde der zweite Thread einen falschen Hash RETURN (einen Zwischenwert der Berechnung in dem ersten Thread) wenn Sie das Attribut direkt verwenden.

+1

Beachten Sie, dass die Thread-Sicherheit hier nicht verhindert, dass der Hash von mehr als einem Thread berechnet wird. Da es keinen Synchronisationsmechanismus gibt, gibt es keine Garantie dafür, dass a) zwei Threads nicht auf "hash" zugreifen, solange es noch "0" ist, und b) dass selbst nach einem Thread das Caching kein anderer Thread das Ergebnis sehen wird. Warum ist es threadsicher obwohl es vielleicht viele Male berechnet wird? Weil die Berechnung idempotent ist; Keine zwei Threads können unterschiedliche Werte berechnen. –

+2

Völlig richtig, Lew. In diesem Fall hat die Berechnung des doppelten Hash-Werts zu Beginn eine geringe Auswirkung, verglichen mit dem Vorteil, dass kein Synchronisationsmechanismus während der Lebensdauer des Strings benötigt wird. – Mario

1

Um es ganz einfach zu sagen: lokale primitive h ist gut lokale; somit fadensicher; im Gegensatz zu hash, die geteilt wird.

Verwandte Themen