2013-09-25 12 views
5

ho la classe inferioreUn blocco sulla classe blocca anche le variabili di classe? - 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 
     } 
    } 
} 

Sarà l'iteratore() chiamata nel metodo printElement buttare ConcurrentModificationException? La domanda di base è se il blocco su oggetto di classe viene acquisito (come fatto nel metodo printElement), bloccherà anche i membri/le variabili della classe? per favore aiutami con la risposta.

risposta

6

Does un blocco su di classe, le variabili di serrature di classe troppo? - java

Il blocco si trova sulla vostra esempio, non la classe. E no, blocca solo l'istanza.

La chiamata iteratore() nel metodo printElement lancia ConcurrentModificationException?

Lo farà se il codice in quel metodo modifica l'elenco durante l'iterazione. Ma se tutto il codice in quella classe anche sincronizza, e non hanno dato un riferimento a tale elenco per qualsiasi cosa al di fuori la classe, poi si sa che solo il codice in quel metodo è in esecuzione.

Probabilmente starai meglio, tuttavia, eseguendo la sincronizzazione nell'elenco stesso. In questo modo, anche se hai dato un riferimento all'elenco, assumendo tutto il codice che lo utilizza sincronizza su di esso, si sarà al sicuro da mods concomitanti:

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

Se si stanno dando i riferimenti e vogliono per essere davvero sicuro, o utilizzare una lista restituita da Collections.synchronizedList o qualcosa dal java.util.concurrent package.

+0

l'utilizzo di due blocchi potrebbe provocare alcuni problemi di blocco, quindi rimuoverei il sincronizzato nella firma del metodo – Simiil

+0

@Simiil: * Qualsiasi * blocco può comportare un deadlock. :-) Ma sì, l'ho rimosso, poiché non dovrebbe essere necessario a meno che non ci sia un motivo non mostrato nella domanda. –

+0

Un blocco in realtà non blocca nulla. È usato per bloccare qualcosa :) – extraneon

0

ArrayList tiri ConcurrentModificationException quando ci sarà contemporaneamente modifica sulla raccolta o durante l'iterazione in caso di cambiamento nella struttura di raccolta.

È consigliabile bloccare l'elenco Object resouce. se la lista ha un metodo getter per accedervi dall'esterno, così da fuori potrebbe essere in grado di modificare la struttura.

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

No, un metodo sincronizzato non blocca le variabili oggetto, un metodo sincronizzato bloccherà solo this.

Il codice non è thread-safe, poiché si sta bloccando su oggetti diversi su addElement e printElement. Non c'è nulla che impedisca l'inserimento durante l'iterazione della lista, se entrambi i metodi sono chiamati contemporaneamente.

0

Non hai mai chiamato il metodo addElement, quindi il blocco non ha alcun effetto su questo snippet di codice. Mentre stai iterando su una raccolta, se inserisci/cancella un elemento nella/dalla stessa collezione ottieni ConcurrentModificationException. Da Javadoc:

Ad esempio, non è generalmente ammissibile per un thread per modificare una collezione mentre un altro filo è iterazione di esso.In generale, i risultati dell'iterazione non sono definiti in queste circostanze. Alcune implementazioni di Iterator (comprese quelle di tutte le implementazioni di raccolta di scopi generali fornite da JRE) possono scegliere di lanciare questa eccezione se viene rilevato questo comportamento. Gli iteratori che lo fanno sono noti come iteratori a prova di errore, poiché falliscono rapidamente e in modo pulito, piuttosto che rischiando un comportamento arbitrario e non deterministico in un tempo indeterminato nel futuro.

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

Sì, se addElement e printElement è chiamato da due thread simultaneously.To evitare, ConcurrentModificationException, è possibile utilizzare CopyOnWriteList.

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

metodo sincronizzata printElement sarà acquisire il blocco di questa object.Hence esso non permetterà un altro metodo sincronizzato o synchornized (questo) blocco di essere chiamato allo stesso tempo, nella classe, se c'è.

Problemi correlati