2017-01-24 6 views
4

はJDKからProperties.listの実装です:印刷前にProperties.listのコピーテーブルがなぜですか?ここ

public void list(PrintWriter out) { 
    out.println("-- listing properties --"); 
    Hashtable<String,Object> h = new Hashtable<>(); 
    enumerate(h); 
    for (Enumeration<String> e = h.keys() ; e.hasMoreElements() ;) { 
     String key = e.nextElement(); 
     String val = (String)h.get(key); 
     if (val.length() > 40) { 
      val = val.substring(0, 37) + "..."; 
     } 
     out.println(key + "=" + val); 
    } 
} 

ライン用

Hashtable<String,Object> h = new Hashtable<>(); 
enumerate(h); 

は何ですか?コピーを作成してそこからデータを読み込む代わりに、元のテーブルを使用するだけではありませんか?

+0

GeraldMückeさんの回答(現在削除されている)は正しいです。その理由は、デフォルトのセットを持つ 'Properties'オブジェクトと関係があります。デフォルトオブジェクトのセットは、それ自体が' Properties'オブジェクトです。既定のチェーンの後のエントリは、以前のエントリによってスクリーニングされます。'enumerate'メソッドはエントリーを再帰的に1つのテーブルに平坦化し、それを出力します。フラット化されたコピーを作成することは、デフォルトのセマンティクスを実装する最も簡単な方法です。 –

答えて

2

list()メソッドは同期されていません。
list()の呼び出し中にPropertiesインスタンス上の呼び出し(同期されているものさえも)が発生すると、オブジェクトの状態が破損し、結果が例外または破損したロジックになる可能性があります。

代わりに中間的な性質インスタンスを使用して、我々はPropertiesインスタンス上で直接繰り返すことが


安全は、我々は二つのスレッドがあると何のスレッドないだろうと仮定します呼び出します。この list()方法とスレッドBを呼び出し、そのスレッド同じ Propertiesインスタンスの remove()

list()メソッドのこのコードには、複数の競合条件があります。例示する

、我々は、(リストのこのスニペットを使用することができる)方法:

String key = e.nextElement(); 
    String val = (String)h.get(key); 
    if (val.length() > 40) { 

は、スレッドAは、この命令の後に一時停止していると仮定:

String key = e.nextElement(); 

スレッドBが再開し、呼び出しましたinstance.remove()は、スレッドAによって検索されたキーに関連するオブジェクトをパラメータとして持つ。

スレッドAが再開されると、次の指示に進むイオン:

String val = (String)h.get(key); 

値はもう存在しません。 valがnullあるよう

次の命令は、例外が発生します:

if (val.length() > 40) { 
+1

ハッシュテーブル 'h'は、' enumerate'が呼び出されたときのプロパティの状態のスナップショットです。これは、スレッドBが使用できるテーブルとは異なるハッシュテーブルです。 h.get(key)が失敗するリスクはありません。 –

+0

@Klitos Kyriacou私は知っています。それは私の悪です。私はその形で十分具体的ではなかった。私は更新しました。それは良いですか? – davidxxx

+0

ああ、それは今良いです。 –

2

スレッドセーフな反復を可能にするのは一般的なイディオムです(つまり、ループ中に別のスレッドがハッシュテーブルを変更している場合に発生する可能性はありません。ConcurrentModificationException)。

+2

これは少し誤解を招く:ConcurrentModificationExceptionは一般的にスレッドの安全性とは関係がないことに注意してください。 –

+0

どのように誤解を招くかはわかりませんが、クリティカルセクション(反復の列挙)中の競合状態(別のスレッドからの副作用)の非常に一般的な症状です。 「スレッドの安全性とは何の関係もありません。」 –

1

これは、マルチスレッド・アプリケーションの最適化です。

Propertiesオブジェクトはスレッドセーフであることを意味するので、メソッドを同期させる必要があります(これは、ロックを保持している間にブロックすることができません)。同期されたブロック(enumerateが同期されている)内の新しいハッシュテーブルにコンテンツをすばやくコピーし、ロックを保持せずにコピーのアイテムを印刷します。

関連する問題