1

参加している分散プログラミングコース用のJavaWebサービスサーバーの開発を終えたところです。要件の1つは、プロジェクトのマルチスレッドセーフを保証することでした。そのため、ConcurrentHashMapオブジェクトを使用してデータを保存することにしました。最後に、このコードスニペットに関する質問が残ります。

    public List<THost> getHList() throws ClusterUnavailable_Exception{

    logger.entering(logger.getName(), "getHList");
    if(hMap==null){
        synchronized(this){
            if(hMap==null){
                hMap=createHMap();
            }
        }
    }
    if(hMap==null){
        ClusterUnavailable cu = new ClusterUnavailable();
        cu.setMessage("Data unavailable.");
        ClusterUnavailable_Exception exc = new ClusterUnavailable_Exception("Data unavailable.", new ClusterUnavailable());
        throw exc;
    }
    else{
        List<THost> hList = new ArrayList<THost>(hMap.values());
        logger.info("Returning list of hosts. Number of hosts returned = "+hList.size());
        logger.exiting(logger.getName(), "getHList");
        return hList;
    }
}

マルチスレッド環境でサービスが予測できない動作をしないことを保証するために、concurrenthashmapオブジェクト自体を作成するときにsynchronizedステートメントを使用する必要がありますか?

4

4 に答える 4

7

気にしないでください。を熱心に初期化しMap、フィールドをファイナルにし、実際に必要であることが証明されるまで同期をドロップします。コストはごくわずかであり、「明らかに安全で正しい」ソリューションが遅すぎることはほとんどありません。

これはクラスプロジェクトだとおっしゃいましたが、コードを機能させることに重点を置いてください。並行性は、ハードルを越えなければならない追加の障害を発明することなく、十分に困難です。

于 2013-01-30T02:26:16.323 に答える
5

簡単な解決策は、熱心に初期化することによって問題を回避することです。そして、熱心な初期化がパフォーマンスの問題であるという明確な証拠(つまりプロファイリング)がない限り、それも最善の解決策です。

あなたの質問に関しては、答えはsynchronizedブロックが正確さのために必要であるということです。これがないと、次の一連のイベントが発生する可能性があります。

  • スレッド1の呼び出しgetHList()
  • スレッド1はそれhMapを確認nullし、マップの作成を開始します。
  • スレッド2の呼び出しgetHList()
  • スレッド2はそれhMapを確認nullし、マップの作成を開始します。
  • スレッド1は作成を終了し、新しいマップをに割り当て、hMapそのマップを返します。
  • スレッド2は作成を終了し、 2番目の新しいマップをに割り当て、hMapそのマップを返します。

つまり、スレッド1とスレッド2は、初期値を持っているときに同時に呼び出すと、異なるマップを取得する可能性があります。getHList()hMapnull


getHList()(上記では、これがのゲッターであると想定していhMapます。ただし、記述されたメソッドはコンパイルされず、宣言された戻り型は...の型と一致しないため、実際の目的hMapは不明です。すること。)

于 2013-01-30T02:48:31.737 に答える
1

以下の行は、ConcurrentHashMapとは何の関係もありません。ConcurrentHashMapオブジェクトのインスタンスを作成するだけです。これは、JAVAでのオブジェクト作成を同期するのと同じです。

hMap=new ConcurrentHashMap<BigInteger, THost>();

于 2013-01-30T01:37:04.937 に答える
0

ダブルチェックロックパターンは、Java 1.5より前では壊れています(Java 1.6以降では非効率的です)。参照:http ://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

初期化オンデマンドホルダーまたは単一要素列挙型の使用を検討してください。

于 2013-01-30T01:46:56.567 に答える