2013-09-25 9 views
5

Ich habe die unten KlasseVerriegelt eine Klasse, sperrt auch Klassenvariablen? - 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 
     } 
    } 
} 

Wird der iterator() -Aufruf in der printElement Methode ConcurrentModificationException werfen? Die grundlegende Frage ist, ob die Sperre für das Klassenobjekt erhalten wird (wie in der Methode printElement), wird es auch die Klassenmitglieder/Variablen sperren? Bitte hilf mir bei der Antwort.

Antwort

6

Ist eine Sperre auf Klasse, Schlösser Klassenvariablen zu? - java

Ihr Schloss ist auf dem Instanz, nicht Ihre Klasse. Und nein, es sperrt nur die Instanz.

Ruft der iterator() -Aufruf in der printElement-Methode ConcurrentModificationException?

Es wird, wenn der Code in dieser Methode die Liste während der Iteration ändert. Aber wenn alle Ihre Code in dieser Klasse auch synchronisiert, und Sie keinen Verweis auf diese Liste etwas außerhalb Ihre Klasse gegeben haben, dann wissen Sie, dass nur der Code in dieser Methode ausgeführt wird.

Sie wären wahrscheinlich besser dran, wenn Sie auf der Liste selbst synchronisieren.

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 
     } 
    } 
} 

Wenn Sie Referenzen geben und wollen: Auf diese Weise, auch wenn Sie einen Verweis auf die Liste ausgegeben haben, die gesamten Code unter der Annahme, dass es synchronisiert auf sie verwendet, werden Sie von Concurrent Mods sicher seine zu sein wirklich sicher, entweder verwenden Sie eine Liste von Collections.synchronizedList oder etwas aus der java.util.concurrent package zurückgegeben.

+0

mit zwei Sperren möglicherweise einige fiese Deadlocks führen, so würde ich die synchronisierte in der Methode Signatur entfernen – Simiil

+0

@Simil: * Any * Sperre kann zu einem Deadlock führen. :-) Aber ja, ich habe es entfernt, da es nicht notwendig sein sollte, außer es gibt einen Grund, der in der Frage nicht gezeigt wird. –

+0

Ein Schloss sperrt eigentlich nichts. Es wird verwendet, um etwas zu sperren :) – extraneon

0

ArrayList löst ConcurrentModificationException aus, wenn gleichzeitig Änderungen an der Sammlung oder während der Iteration im Falle einer Änderung der Sammlungsstruktur vorgenommen werden.

Sie sollten besser die Liste Objekt resouce sperren. Wenn die Liste Getter-Methode hat, um auf sie zuzugreifen, könnte sie die Struktur ändern.

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

Nein, eine synchronisierte Methode sperrt die Objektvariablen nicht, eine synchronisierte Methode sperrt nur this.

Ihr Code ist nicht Thread-sicher, da Sie verschiedene Objekte auf addElement und printElement sperren. Es gibt nichts, was verhindert, dass die Einfügung beim Iterieren der Liste auftritt, wenn beide Methoden gleichzeitig aufgerufen werden.

0

Sie haben nie die Methode addElement aufgerufen, daher hat das Sperren keine Auswirkungen auf dieses Code-Snippet. Während Sie über eine Sammlung iterieren, erhalten Sie ConcurrentModificationException, wenn Sie Elemente aus derselben Sammlung einfügen/löschen. Von Javadoc:

Zum Beispiel ist es im Allgemeinen nicht zulässig für einen Thread eine Sammlung zu ändern, während ein anderer Thread über sie iteriert.Im Allgemeinen sind die Ergebnisse der Iteration unter diesen Umständen nicht definiert. Einige Iterator-Implementierungen (einschließlich derjenigen aller von der JRE bereitgestellten allgemeinen Sammlungsimplementierungen) können diese Ausnahme auslösen, wenn dieses Verhalten erkannt wird. Iteratoren, die dies tun, werden als Fail-Fast-Iteratoren bezeichnet, da sie schnell und sauber ausfallen und stattdessen willkürliches, nicht-deterministisches Verhalten zu einem unbestimmten Zeitpunkt in der Zukunft riskieren.

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

Ja, wenn addElement und printElement von zwei Threads aufgerufen wird simultaneously.To zu vermeiden, ConcurrentModificationException, könnten Sie CopyOnWriteList verwenden.

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

synchonized Methode printElement wird die Sperre dieses object.Hence aquire es wird nicht eine andere synchronisierte Methode oder synchornized (this) Block ermöglichen gleichzeitig aufgerufen werden, in der Klasse, wenn es irgendwelche gibt.