1

2つのスレッドが同時にアクセスした場合、次のコードでパラメータマップがどのように影響を受けるかを誰かに説明してもらえますか?マップは同期ブロック内にないため、スレッドセーフの問題にさらされていますか?

public void fun(String type, String name, Map<String, Object> parameters) {
    parameters.put(Constants.PARM_TYPE, type);
    parameters.put(Constants.PARM_NAME, name);
    try {
        synchronized (launcher) {
            launcher.launch(type, bool, parameters);
        }
    } catch (Exception e) {
        logger.error("AHHHHH, the world has ended!",e);
    }
}

私は以下を見てきましたが、私はまだそれを疑問視しています:同期と可視性の範囲

4

5 に答える 5

1

複数のスレッドが同じインスタンスへのハンドルを持ち、parametersスレッドセーフではないマップ実装を使用してこのメ​​ソッド(マップを変更する)を呼び出す場合、あらゆる種類の悪いことが発生する可能性があります(たとえば、マップの破損が発生する可能性があります)。 NullPointerExceptionのような例外としてそれ自体)。

于 2013-03-04T16:38:42.697 に答える
1

共有マップがあるとします。

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

あなたの例に示されているように、多くのスレッドによって更新されています。

new Thread(new Runnable(){
    public void run(){
        fun("a","b", map);
    }
}).start();
new Thread(new Runnable(){
    public void run(){
        fun("a","b", map);
    }
}).start();

各スレッドが同時にマップを更新する可能性があり、美しい競合状態につながる可能性があります

于 2013-03-04T16:41:22.853 に答える
1

parametersインスタンスが分離している場合(最後のコメントで述べたように)、このコードに問題はありません。

さらに、メソッドのパラメーターMap parametersはわずか 2String秒なので、それらに関する同期の問題はありません。

synchronizedブロックをメソッドレベルまたは上に配置するには:launcherそれらは異なるオブジェクトです。メソッドを配置すると で同期されthis、そうでない場合は で同期されlauncherます。「ランチャー」を保護したいので、できるだけ近くに「フェンスを構築」する必要があります。そのため、同期launcherは問題ありません。

を使用し、そのオブジェクトで同期を行う別の手法がありObject lockObject = new Object()ますが、この用途ではやり過ぎだと思いますが、それは可能です。

于 2013-03-04T17:32:58.543 に答える
0

複数のスレッドがメソッドにアクセスしていると仮定するとfun()、マップが機能する方法は、同じキーを複数回挿入すると、そのキーの値が毎回上書きされることです。しかし、これだけが問題ではないかもしれません。競合状態や破損の問題も発生する可能性があります。暗黙的にスレッドセーフなデータ構造が必要な場合は、HashTableがあなたの仕事を成し遂げると思います。

于 2013-03-04T16:38:18.797 に答える
0

複数のスレッドがそのコードを同時に実行し、同じオブジェクトをパラメータ マップとして渡すと、競合状態が発生します。

次の場合を除き、これは確実にスレッド セーフの問題を引き起こします。

  • 要件と Map 実装の同時動作に基づいて、適切な Map 実装を使用します (たとえば、 ConcurrentHashMapですが、これはアプリの実際の要件に大きく依存します)

  • または、自分でスレッド セーフ コードを記述します (おそらく、「synchronized」などの同期プリミティブを使用します)。

重要:マップを変更するコード行を同期ブロックに移動するだけでは、必ずしも競合状態が解消されるとは限らないことに注意してください。これは、アプリ内の他のどのスレッドがマップを変更しようとし、どのオブジェクトが変更を試みているかを考慮する必要があるためです。アクセスを同期するために使用します。関数内のコードは、「ランチャー」への参照を使用して同期しています。同期せずに、または「ランチャー」とは異なるオブジェクトを介して同期してマップを変更する他のスレッドは、競合状態を引き起こします

于 2013-03-04T17:22:08.300 に答える