2017-10-24 4 views
3

Peter Lawryのブログhereにこのコードが見つかりました。彼は、このクラスはそれ以上の同期を必要としないと述べている。同期なしでデータを共有する - このコードはスレッドセーフですか?

私は同時性に関する知識と不要な同期を回避する方法を改善しようとしていますので、このケースについてJavaメモリモデルの観点から推論する方法を考えようとしています。

文字列配列への参照が最終的なもので、文字列自体は不変ですが、配列に含まれる文字列への参照が変更可能です

  • は、あるスレッドがまだ見ることができること、それは、少なくとも理論的には可能ではありません別のスレッドが値を更新した後はnullですか?
  • 文字列が複数回使用されている場合は気にしませんか?
  • また、JVMには、私が紛失しているという追加の保証がありますか?あなたのケースでは

    public class StringInterner { 
        private final String[] interner; 
        private final int mask; 
    
        public StringInterner(int capacity) { 
         int n = Maths.nextPower2(capacity, 128); 
         interner = new String[n]; 
         mask = n - 1; 
        } 
    
        private static boolean isEqual(@Nullable CharSequence s, @NotNull CharSequence cs) { 
         if (s == null) 
         return false; 
         if (s.length() != cs.length()) 
         return false; 
         for (int i = 0; i < cs.length(); i++) 
         if (s.charAt(i) != cs.charAt(i)) 
          return false; 
         return true; 
        } 
    
        @NotNull 
        public String intern(@NotNull CharSequence cs) { 
         long hash = 0; 
         for (int i = 0; i < cs.length(); i++) 
         hash = 57 * hash + cs.charAt(i); 
         int h = (int) Maths.hash(hash) & mask; 
         String s = interner[h]; 
         if (isEqual(s, cs)) 
         return s; 
         String s2 = cs.toString(); 
         return interner[h] = s2; 
        } 
    } 
    

答えて

2

私たちは文字列が二回インターンされていることを気にしないと思います。メモリモデルは、配列の値を代入するときに何の悪も起こらないように注意します。関連する質問があります:java array thread-safety

データが安全であるため、並行処理の観点からは同期なしで動作しています。したがって、クラスは並行アクセスで正しく機能しています。

インターンが一度しか起こらないようにするには、同期が必要なのですが、その価格は厳格であることが望ましい場合は、どのような正しさがあなたのユースケースに依存しています。 (gudokが指すよう:並行処理とは独立して、まだインターンが原因でハッシュの複数回起こる)

+0

注意を並列実行固有ではありません。これは、複数の文字列が同じバケットにハッシュする可能性があるためです。 – gudok

+0

@gudok:はい、それは本当です。私はただの視点から見ていただけだった。私は答えにそれを追加します – Sorontur

+0

@Sorontur - あなたの答えをありがとう、確認するために、スレッドが別のスレッドの後に文字列(nullまたは以前に格納された値)の古い値を見ることができると推論するのは正しいですか?そのメモリ位置に文字列を格納していますか? - シェーン50分前 – Shane

0

私は視界についてSoronturコメントに同意します。このコードは予期しない結果を生むことがあります(シナリオを再現するのは難しいことがあります)。 internメソッドはスレッドセーフではないようです。複数のスレッドは、複数のコアで並列に実行できます。通常、各コアにはそれぞれ独自のキャッシュがあります。 1つのスレッドがinternの変数を更新すると、すぐにキャッシュが更新されますが、他のコアのキャッシュは同時に更新されませんが、他のスレッドは古い値を使用することがあります。したがって、このような状況には、volatile変数を使用できますが、パフォーマンスに影響します。したがって、shared memory modelのマルチスレッドは、パフォーマンスと効率のトレードオフです。

注:そのインターンが複数回発生しません。でも、明示的な同期保証するものではありません:私は、予期しない動作が並行スレッドで見ることができだと思う、

関連する問題