2011-06-22 14 views
1

複数のスレッドからaddIdメソッドを呼び出すときに競合が発生する可能性がありますか?以下のコードで競合状態が発生する可能性があります

private static Map<String , Long> table; 

static { 
    table = new ConcurrentHashMap<String , Long>(); 
} 

public static void addId(String key, Long value){ 

    if(table.containsKey(key)){ 
     table.remove(key); 
    } 

    table.put(key, value); 
} 
+0

1行に 'table'を宣言することができます。 –

+0

1行での宣言は、静的なクラスコード内での宣言と同じですか? –

+0

はい、ただし4行ではなく1行が必要です。私はまた、 'テーブル' finalを作るだろう –

答えて

8

何もので、テーブルがすでに入れる前にキーが含まれているかどうかをチェックすることは、本当に「安全」(というか、本当にないではない、containsKey/removeputの間でいくつかの値を入れてから、他のスレッドを防止していません"意味がある")。あなただけ

public static void addId(String key, Long value){ 
    table.put(key, value); 
} 

putをしないのはなぜ

はとにかく、以前のエントリを上書きします。


あなたは​​としてメソッドを宣言し、複数のスレッドが同時にメソッドを実行したくない場合。

2

はい。

(私の答えは30文字以上でなければならないことと思われる)

addId呼び出しが競合状態を与えたことができます:1つのスレッドの鍵を置くことを試みることができるもう一つは、同時にキーを削除することができます(同じキーであれば、問題になる可能性があります)。その方法の中には、(さまざまな結果を伴う)競争状態を得ることができる2つ以上のケースがあります。

これは、他の方法、つまりテーブルからの読み取りを行う方法があると、さらに複雑になり、競合状態が上書きされた値よりもずっと悪くなります。

最終的に、あなたは何を求めていますか?あなたは競争状態を避ける方法を疑問に思っていますか?マップクラスの残りの部分は何をしていますか?

+0

クラスの残りの部分は、テーブルから値を返すアクセサメソッドを持っています –

+0

私の質問は少し見えた場合は、競争状態を避けるために、曖昧。ありがとうございました! –

2

はい、競合状態が発生する可能性があります。

if(table.containsKey(key)){ 
     table.remove(key); 
    } 

    table.put(key, value); 

別のスレッドでは、containsKey、remove、putの間でテーブルを変更する可能性があります。ただし、put()を実行する前にremove()を呼び出す必要はありません。containsKey/removeを削除すれば、スレッドセーフになります。

0

置き換えられたときに古い値で何かが行われたことを保証したい場合は、レースによって上書きされたキーをすべて処理できなくなる可能性があります。

if(table.containsKey(key)){ 
    Long oldValue = table.remove(key); 
} 
table.put(key, value); 
if (oldValue != null) 
    importantOperation(oldValue); 

編集:

これは、(他の人が指定されているとして)1があった場合、古い値を返すので、チェックはまだ必要ありませんもputのように見えます。小切手は、以下の厄介な状況で必要になります。これは、レースに関係するでしょう:

if(table.containsKey(key)){ 
    Long oldValue = table.remove(key); 
    value = secretlyAdjustInput(oldValue, value) 
} 
table.put(key, value); 
関連する問題