0

簡単な質問です。次のコードはスレッドセーフですか...?

  1. はいの場合、何か良い方法はありますか..?
  2. いいえの場合、なぜですか。どうすればスレッドセーフにできますか。

私の主な疑問は、スレッドセーフではないArrayListためHashtableです。ArrayListの一部の場合も同じことが起こりHashtableます。

Hashtable<Thread, List<String>> threadObjects = new Hashtable<Thread, List<String>>();
 // lets assume some object is added. 
 synchronized (threadObjects)
  {
     thread = Thread.currentThread();
     List<String> v =  threadObjects.get(thread);
     if (null != v)
     {
       // do something
     }
  }

ありがとう

4

3 に答える 3

5

はいの場合、何か良い方法はありますか..?

はい、ただし ThreadLocal> を使用します

ArrayList はスレッドセーフではないため、Hashtable 内の ArrayList が主な疑問です。

通常はその通りですが、このコードにより、ArrayList が 1 つのスレッドのみによってアクセスされることが保証されます。もちろん、このパターンに従わなければ、スレッド セーフになります。

注:synchronized (threadObjects)この場合、違いはありません。

于 2013-01-17T13:52:16.953 に答える
4

次のコードはスレッドセーフですか...?

はい...ただし、次の場合:

  • マップを作成してエントリをマップに追加するコードもスレッドセーフです。
  • (コードに従って)同期せずにマップを使用する他のコードはありません。
  • マップ上で同期せずにリスト オブジェクトを更新するコードはありません。

外部同期データ構造のスレッド セーフは、そのデータ構造を使用するすべてのコードを調べることによってのみ判断できます。

Peter が述べているように、ThreadLocals はより良い解決策ですが、適切なロックなしでリスト オブジェクトが変更された場合、潜在的なスレッド セーフの問題が依然として存在します。

于 2013-01-17T14:41:44.537 に答える
3

ThreadLocal を使用して、スレッド固有のデータを格納できます。例えば:

private final ThreadLocal<List<String>> threadObjects =
    new ThreadLocal<List<String>>() {
        @Override protected List<String> initialValue() {
            return new ArrayList<String>();
        }
    };

public void foo() {
    for (String s : threadObjects.get()) {
        // do something with each string in this thread's list
    }
}

Hashtableこれは、同期を含む ThreadLocal 実装自体の内部でテーブルが維持されるため、この方法よりもスレッド固有のデータを追跡する方法としてはるかに優れています。ArrayList他のスレッドへの参照を発行しない限り、インスタンスで追加の同期は必要ありません。ArrayList各スレッドには、並行性を気にせずに処理できる独自のインスタンスがあります。

のオーバーライドは、スレッド ローカルを に明示的に設定しないことを前提として、の結果initialValue()に対する のチェックを回避できるため便利です。nullthreadObjects.get()null

于 2013-01-17T14:55:17.767 に答える