2017-04-27 18 views
10

JavaのStringクラスを見ると、最初の評価後にハッシュコードがキャッシュされていることがわかります。java文字列ハッシュコードキャッシュメカニズム

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

ここで、hashはインスタンス変数です。私には質問がありますが、なぜそれが必要でしょうかh余分な変数はありますか?

+1

'String'クラスがスレッドセーフであることを保証するために、このように記述されています。このコンセプトについての詳細はこちら[こちら](https://en.wikipedia.org/wiki/Thread_safety) – Valy

+1

ウィキペディアのリンクでは、ここで何が起こっているのか、その理由を詳しく説明していません。 –

答えて

5

単にループ内で値が変更され、中間の一時変数を持たないソリューションはスレッドセーフではないためです。このメソッドが複数のスレッドで呼び出されたとします。

と言うと、thread-1はで始まり、が開始されました。後で少しの瞬間であるthread-2は、同じオブジェクトの同じメソッドhashCode()を呼び出し、hash0ではないと考えていますが、thread-1はまだ計算を完了していません。その結果、thread-2では、hash(完全には計算されていない)値が使用されます。

3

シンプルで安価な同期メカニズムです。

スレッドが最初にhashCode()を呼び出し、2番目のスレッドが最初のスレッドがハッシュを計算している間に2番目のスレッドが再度呼び出すと、2番目のスレッドは不正なハッシュを返します(最初のスレッド)属性を直接使用する場合

+1

ここでのスレッドの安全性は、ハッシュが複数のスレッドによって計算されるのを妨げないことに注意してください。同期メカニズムがないため、a)2つのスレッドがまだ「0」である間に2つのスレッドにハッシュにアクセスしない、またはb)1つのスレッドがキャッシングを行った後でも他のスレッドが結果を見ることができないという保証はない。何度も何度も計算されているにもかかわらず、スレッドセーフなのはなぜですか?計算は等式なので、 2つのスレッドが異なる値を計算することはできません。 –

+2

完全に正しい、ルー。その場合、ハッシュを2回計算することは、文字列の存続期間中に同期メカニズムを必要としないという利点と比較して、冒頭に軽微な影響があります。 – Mario

1

非常に簡単に言えば、ローカルプリミティブhは、ローカルです。したがって、スレッドセーフです。共有されているhashとは対照的です。