1

編集された質問:
コードに記載されているように、HashSet と HashMap はフェイルファーストです (ただし、保証されていません)。

void goHashSet() {
        Set set = new HashSet();
        for (int i = 1; i <= 10; i++) {
            set.add(i);
        }
        Iterator i = set.iterator();
        while (i.hasNext()) {
            // set.add(16);//Exception in thread "main"
            // java.util.ConcurrentModificationException
            System.out.println("HashSet >>> itertor >>>" + i.next());
        }
    }

今、私が
知っている限り、例とコレクションがフェイルセーフであることを望みます:

私が欲しいものとそれをどのように達成したかの編集と理解:

HashMap を使用する場合

void goHashMap() {
        Map mp = new HashMap();
        for (int i = 19; i <= 24; i++) {
            mp.put(i, "x");
        }
        Set setKeys = mp.keySet();
        Iterator i = setKeys.iterator();
        while (i.hasNext()) {
            // mp.put(499, "x");// Exception in thread "main"
            // java.util.ConcurrentModificationException
            System.out.println("HashMap >>> itertor >>>" + i.next());
        }
    }

ConcurrentMException を取得します

しかし、同じコードが ConcurrentHashMap で実行され、エラーはありません (非マルチスレッド環境)

void goConcurrentHashMap() {
    Map mp = new ConcurrentHashMap();
    for (int i = 19; i <= 24; i++) {
        mp.put(i, "x");
    }
    Set setKeys = mp.keySet();
    Iterator i = setKeys.iterator();
    while (i.hasNext()) {
        mp.put(499, "x");
        System.out.println("HashConcurrentMap >>> itertor >>>" + i.next());
    }
}

さらに、マルチスレッド環境では、ConcurrentHashmap がフェイルファストになり、例外 CME をスローする可能性があります

4

3 に答える 3

2

HashMap は、フェイル セーフであるとは限りませ。別のスレッドで HashMap を変更しても、別のスレッドに通知されないようにすることができます。OpenJDK バージョンの HashMap は、非volatilemodcount フィールドを使用して同時変更を識別します。不揮発性フィールドはスレッド間で一貫性があることが保証されていないため、あるスレッドがこれを変更しても、別のスレッドはその変更に気付かないことがあります。

これは比較的まれな競合状態であるため、CME が検出される可能性が非常に高くなりますが、テストして 10000 回連続して期待どおりに動作したとしても、探している証拠は得られません。

実際、最初の 10000 回はパスし、その後は一貫して失敗するコードを書くことは可能です。これは、HotSpot コンパイルがこの時点以降にネイティブ コードにコンパイルされるためです。これは、最適化前に正常に実行されたコードが、最適化後に異なる動作をする可能性があることを意味します。不揮発性フィールドの場合は特に。

于 2012-04-18T09:13:44.970 に答える
1

API Javadoc (HashSetとの両方HashMap) は、フェールセーフに対してソフトな保証のみを行います。

イテレータのフェイルファスト動作は保証できないことに注意してください。一般的に言えば、同期されていない同時変更が存在する場合にハードな保証を行うことは不可能であるためです。フェイルファスト イテレータConcurrentModificationExceptionは、ベスト エフォート ベースでスローします。したがって、その正確性をこの例外に依存するプログラムを作成するのは誤りです。反復子のフェイルファスト動作は、バグを検出するためだけに使用する必要があります

同一の動作は、 が内部的HashSetに の上に実装されているという事実によって説明されます。HashMap

ただし、JDK インストールにバンドルされているソース コードを自由にチェックしてください。

アップデート

今、フェイルセーフな例とコレクションが欲しい

java.util.concurrentパッケージ内のコレクションをご覧ください。

私が知っている限り:ConcurrentHashMap、CopyOnWriteArrayListはフェイルセーフです..しかし、それらがフェイルセーフであることを示すためにそれをコーディングする方法

並行性の性質上、テストだけでスレッドセーフ (またはフェイルセーフ) を証明することは不可能です。反対のこと、つまり、特定のクラスがスレッドセーフではないことを証明することしかできません (たまたまそうなった場合)。これがまさに並行処理を難しくしている原因です。

そのようなことを証明するのに最も近いのは、1 人以上の同時実行の専門家による問題のコードの徹底的な分析です。一部の静的分析ツールでもいくつかの問題を検出できますが、ここでも、クリーンな静的分析結果が保証されるわけではありません。

于 2012-04-18T09:10:07.817 に答える
0

ConcurrentHashMap の内部実装を見ると、元のコレクションではなく元のコレクションのクローンで機能することが非常に明確に述べられています。

したがって、理想的には、元のコレクションは初期と同じです...このように、ConcurrentHashMap は COncurrentModifcationException を回避し、フェイルセーフとして呼び出すことができます。

複数のスレッドがマップを変更しようとしているテストプログラムを作成してテストしようとしました..テストを約10回実行しましたが、ConcurrentModification例外がスローされるのは1回もありませんでした。

ConcurentHashMap の実装についてさらに詳しく説明すると、同期メカニズムが通常のハッシュマップとは大きく異なることがわかります。CHM はアルゴリズム セグメンテーション ロックで機能するためです。

于 2013-04-13T11:47:49.940 に答える