4

のドキュメントを読んでいるjava.util.HashMapと、次のように書かれています。

複数のスレッドがこのマップに同時にアクセスし、少なくとも 1 つのスレッドがマップを構造的に変更する場合は、外部で同期する必要があります。

どういう意味ですか?「それ」は、マップを変更するスレッドを意味すると解釈することも、マップ自体を意味することもできます。

「複数のスレッドの読み取りに対して安全」と「ライターがある場合は単一のスレッドでのみ安全」のケースはどちらも(少なくとも私にとっては)簡単なことではありません。ドキュメントは、ステートメントが「ライターがある場合はすべてをロックする」という簡単なことではなく、「複数のスレッドが読み取り、単一のスレッドが書き込みを行っても安全」と解釈する必要があることを意味します。

さらに、.Net でのハッシュテーブルの実装は (明確に) 次のように文書化されています。

Hashtable は、複数のリーダー スレッドと 1 つの書き込みスレッドで使用できるスレッド セーフです。

(.Net クラスはデフォルトではスレッド セーフではありません)、したがって、「複数のリーダー スレッドと 1 つのライター スレッド」の場合には何かが必要です。

4

2 に答える 2

2

スレッドが「マップを構造的に変更する」場合、内部要素は不確定な状態になるため、読み取りが影響を受ける可能性があります。したがって、読み取りと書き込みの両方を同期するために、マップの外部にあるメソッドを使用する必要があります。

おそらく、.Net ライブラリの作成者は、更新中に内部構造を決定的な状態に保つことにもっと注意を払っていたのでしょう。

于 2012-09-16T02:52:26.120 に答える
0

マップそのもの。HashMap はスレッドセーフではありません。

ConcurrentHashMapを見てください。これはスレッドセーフなマップです。

また、自分で管理することもできます。コードはおそらく以下のようになります

class SomeClass {

    private Map<Object, Object> map = new HashMap<Object, Object>();

    public synchronized void put(Object key, Object value) {
        map.put(key, value);
    }

    public synchronized Object get(Object key) {
        return map.get(key);
    }
}

より安全に、予期しない動作を避けるために、値オブジェクトのコピーを返します。

public synchronized ValueType get(Object key) {
    return map.get(key).clone(); // assume that the ValueType implements Cloneable
    // of course, you can return a copy in many ways you like
}

これにより、putメソッドはマップを変更することしかできなくなります。また、すべての操作はスレッドセーフになります。

于 2012-09-16T02:55:21.640 に答える