2013-09-25 8 views
5

私はクラスをロックすると、クラス変数もロックされますか? - Javaの

public class Example{ 

    public static List<String> list = new ArrayList<String>(); 

    public static void addElement(String val){ 
     synchronized(list){ 
      list.add(val); 
     } 
    } 

    public static synchronized void printElement(){ 
     Iterator<String> it = list.iterator(); 
     while(it.hasNext()){ 
      //print element 
     } 
    } 
} 

以下のクラスを持っているprintElement方法でイテレータ()の呼び出しはConcurrentModificationExceptionをスローしますか?基本的な質問は、クラスオブジェクトのロックが取得された場合(printElementメソッドの場合と同様)、クラスメンバー/変数もロックされますか?答えで私を助けてください。

答えて

6

、クラスのロックをいすぎてクラス変数をロック? - java

ロックはあなたのクラスではなく、のインスタンスにあります。そして、いいえ、インスタンスをロックするだけです。

printElementメソッドのiterator()呼び出しは、ConcurrentModificationExceptionをスローしますか?

このメソッドのコードが反復処理中にリストを変更した場合には、このメソッドが変更されます。しかし、そのクラスにおけるすべてのコードもは、とを同期させる場合あなたは何あなたのクラスにそのリストへの参照を与えていない、あなたはだけそのメソッド内のコードが実行されていることを知っています。

リスト自体を同期する方がよいでしょう。あなたが参照を配っている場合

public static void printElement(){ 
//   ^--- No `synchronized ` here unless you REALLY need it for other reasons 

    synchronized (list) { 
     Iterator<String> it = list.iterator(); 
     while(it.hasNext()){ 
      //print element 
     } 
    } 
} 

とします:あなたはそれに同期させ使用するすべてのコードを仮定して、リストへの参照を与えてくれた場合でも、その方法は、あなたが同時改造から安全になるだろう本当にであることを確認するには、Collections.synchronizedListまたはjava.util.concurrent packageから返されたリストを使用してください。

+0

2つのロックを使用するとデッドロックが発生する可能性がありますので、メソッドのシグネチャ内でsynchronizedを削除します。 – Simiil

+0

@Simiil:*任意の*ロックによりデッドロックが発生する可能性があります。 :-)しかし、ええ、私はそれを削除しました。質問に示されていない理由がない限り、必要ではないはずですから。 –

+0

ロックは実際には何もロックしません。それは何かをロックするために使用されます:) – extraneon

0

ArrayList throws ConcurrentModificationExceptionコレクションの変更が同時に行われる場合、またはコレクションの構造が変更された場合は、繰り返しが行われる場合。

リストオブジェクトのロックをよくする必要があります。リストが外部にアクセスするgetterメソッドを持っている場合、外側から構造を変更することができます。

synchronized (list) { 
    Iterator<String> it = list.iterator(); 
    while(it.hasNext()){ 
     //print element 
    } 
} 
1

いいえ、同期メソッドはオブジェクト変数をロックしません。同期メソッドはthisだけをロックします。

addElementおよびprintElementの異なるオブジェクトでロックしているため、コードはスレッドセーフではありません。両方のメソッドが同時に呼び出された場合、リストを反復処理している間に挿入が行われるのを妨げるものはありません。

0

あなたはaddElementメソッドを呼び出さなかったので、ロックはこのコードスニペットには影響しません。コレクションを繰り返し処理している間に、同じコレクションに要素を挿入/削除すると、ConcurrentModificationExceptionが得られます。 Javadocから :

例えば、それは別のスレッドがそれを反復処理している間コレクションを修正するための一つのスレッドのために、一般的には許されません。一般に、これらの状況では、反復の結果は未定義です。この動作が検出された場合、Iterator実装(JREによって提供されるすべての汎用コレクション実装の実装を含む)によっては、この例外がスローされる可能性があります。これを行うイテレータは、フェイル・ファースト・イテレータとして知られています。これらのイテレータは、将来、不確定な時間に任意の非決定論的な動作を実行する危険性があるため、迅速かつきれいに失敗します。

1
Will the iterator() call in the printElement method throw ConcurrentModificationException? 

はaddElementとprintElementは、ConcurrentModificationExceptionを避けるsimultaneously.To二つのスレッドによって呼び出された場合は、[はい、あなたはCopyOnWriteListを使用することができます。

if the lock on class object is acquired(as done in printElement method), will it lock the class members/ variables too? 

synchonized方法printElementが、それは文句を言わない他のsynchronizedメソッドまたはsynchornized(この)ブロックの任意がある場合は、あなたのクラスで、同時に呼び出すことができるようにするこのobject.HenceのロックをAQUIREます。

関連する問題