2011-12-05 9 views
3

私はいくつかのプライベートハッシュマップを宣言し、いくつかの方法でそれらを更新するスプリングコントローラをコーディングしています。もちろん、私は同時アクセスの問題を認識しているので、私はこれらの問題を回避する最も簡単な方法を使用しています: "同期化された" Javaスレッドセーフ機能。しかし私は自分のメソッドを同期するべきか、または安全に更新する必要があるハッシュマップだけを同期するべきかどうか疑問に思っていました。これらのメソッドは同等ですか?私はアプリケーションの同じ動作をしますか?Javaスレッドセーフ、データ競争と良い実装

+4

ConcurrentHashMapを代わりに使用している理由は何ですか? –

+0

@Jon:Jillesへの返信を参照してください。 – Zamboo

答えて

2

myHashMap変数がプライベートで、myControllerメソッドを介してのみアクセスできる場合は、メソッドを同期する必要があります。別の方法として、メソッドを同期させるとスレッドセーフになりますが、同期ブロック/メソッドを使用せずにmyHashMap変数に直接アクセスすると、ロックを覆すことができます。

さらに簡単に言えば、あなたは一度に1人の人を許可するドアがある部屋があれば、一度に部屋に1人しかいないでしょう...しかし、部屋に窓を置くと、あなたはまだ窓からの部屋。 :)

EDIT:詳しく説明します。このメソッドにsynchronizedをキーワードとして設定することで、メソッド全体のクリティカルセクションが作成されます。つまり、メソッド呼び出しの終了からそのオブジェクトで実行できることは他にありません。クローズブロックを使用することで、クリティカルセクションを必要に応じて出入りすることができます。 100行のメソッドがあるとします。共有リソースを使用するために必要な10行について、メソッドにsynchronizedを置くと、オブジェクトは100行全体に対してロックされますが、ロックを10行だけに置くとあなたが必要とする行は、10行にはクリティカルセクションしかありません。

あなたがいる状況はすべてです。あなたが与えた例では、全く違いはありません。

+0

大きな違いがあります。同じオブジェクトでは同期していません。ここでは問題にはならないように見えるかもしれませんが、その例は明らかに不完全なので、言い難いです。 – Bruno

+0

合意。簡単に質問に答えるために、回答は同じではありません。たとえば、myControllerオブジェクトをロックしている最初の例では、2番目にhashmapオブジェクトをロックしています。 –

+1

あなたの最後のパラグラフでは、「他に何もそのオブジェクトを実行することはできません」ということは、「同じインスタンスオブジェクト*上で同期するものは何も実行できません」ということを明確にするのに非常に役立つと思います。 'synchronized'ブロックが何か他のことが起こるのを止めるのに対し、' synchronized'ブロック/メソッド(同じモニター上)で起こる他のアクションだけをブロックするのは、初心者の間違いです。 –

3

これらの方法は同等ではありません。方法に

​​

ので、thisに同期化:thismyControllerのインスタンスであり、ここで

public updateMyHashmap(){ 
    synchronized(this) { 
     myHashMap.add(value); 
    } 
} 

public synchronized updateMyHashmap(){ 
    myHashMap.add(value); 
} 

と等価です。 (サイドノート:Javaでは大文字でクラス名を開始することをお勧めします)。

静的メソッドから非静的メンバー(myHashMap)にアクセスしているため、2番目の方法が正しくないため、コンパイルしないでください。

静的ではないと仮定すると、myControllerインスタンスではなくハッシュマップで同期します。

あなたが同期したいものは、この同期ブロックで何をしたいかによって決まるでしょう(例えば、valueはどこから来たのでしょうか?操作はmyControllerインスタンスを使用して同期する必要があります)。

同期の問題の詳細については、Java Concurrency in Practiceをお読みください。

0

私はConcurrentHashMapを使用し、手動でアクセスを同期させないでください。

メソッドを静的にすることは、ここではあまり役に立ちません。特に、同期するオブジェクトが必要なので、これは通常これです。

+1

staticメソッドを 'synchronized'として宣言すると、メソッドを宣言するクラスの' Class'オブジェクトと同期します。したがって、同期するデフォルトのオブジェクトが不足する心配はありませんが、メソッドを静的にすることはスレッドセーフの問題とは無関係です。 –

+0

@Jilles:java docによると: "ただし、すべての操作がスレッドセーフであっても、検索操作はロックを伴わず、すべてのアクセスを阻止する方法でテーブル全体をロックするためのサポートはありません。" – Zamboo

+0

@Zambooなぜあなたは*それを望んでいますか?すべてのアクセスを阻止するロックが必要な達成しようとしているのは何ですか? –

0

この2つは異なるものですが、同じ種類の目的を達成するために使用できます。

だから、私はあなたが今簡単にこれらの2つの戦略の違いを見ることができると思い

public updateMyHashmap(){ 

    //Some code here 

    System.out.println("Inside method") 

    synchronized(this) { 
     myHashMap.add(value);  
    } 
} 

この方法では今、ここに

//Here you are locking your method 
public synchronized updateMyHashmap(){ 

    System.out.println("Inside method"); 

    //some code 

    myHashMap.add(value); 
} 

を参照してください。それはあなたがしたいことに依存し、それに応じてあなたはそれらのどれかを選ぶことができます。

ロックしたいオブジェクトを同期することをお勧めします。

+0

私がしたいことは、ハッシュマップデータを正しく更新させるために「ちょうだい」です:ハッシュマップの更新プロセスが開始されると(それはいくつかのメソッドが呼び出すことができます...)、その後、他のスレッドのデータ – Zamboo

関連する問題