Rendere tutti i metodi su una classe individualmente sincronizzati non rende aggregabili (chiamandoli in un gruppo) di questi metodi thread safe. Racchiudendo lo Iterator
in un blocco sincronizzato, si protegge quella particolare istanza dell'iteratore dal fatto che il suo singolo metodo è denominato intercalato con altre chiamate da più thread.
Se chiamo .add()
una volta che è sicuro, se ho bisogno di chiamare .add()
più volte per completare una frase di senso, non v'è alcuna garanzia che qualcun altro non ha aggiunto qualcos'altro o qualcosa rimosso altro tra i miei .add()
chiamate a meno che non blocca tutto il resto chiamando lo .add()
(o qualsiasi altro metodo) per synchronizing
sulla variabile che rappresenta la raccolta.
Il Iterator
rende mutiple chiamate ai singoli metodi per la raccolta, tutti devono essere avvolti in un unico blocco synchronized
per farli eseguire come un singolo transaction
di sorta. Esaminare il codice sorgente dell'implementazione di Iterator
vedrete cosa intendo. Ecco il codice sorgente per List
effettua più chiamate individuali all'implementazione sottostante, quindi devono essere eseguite in ordine ininterrotto dallo stesso thread per essere deterministiche.
@Override
public Iterator<A> iterator() {
if (tail == null)
return emptyIterator();
return new Iterator<A>() {
List<A> elems = List.this;
public boolean hasNext() {
return elems.tail != null;
}
public A next() {
if (elems.tail == null)
throw new NoSuchElementException();
A result = elems.head;
elems = elems.tail;
return result;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
Il source per AbstractList.iterator()
mostra ancora logica più complicato che rende più chiamate.
Un wrapper migliore li sta avvolgendo nelle raccolte Immutable
, quindi si garantisce che nient'altro può modificare la raccolta sottostante tra le chiamate.
fonte
2013-04-03 21:00:36
Cosa intendi per "implica necessariamente più chiamate di metodo separate"? – user697911
@ user697911: 'i.hasNext()' e 'i.next()' sono due chiamate di metodo separate e non esiste alcun modo per l'implementazione di 'Collections.synchronizedCollection' per garantire che nulla cambi tra' i.hasNext() 'e' i.next() '. –
Quindi, concurrentHashmap sarebbe lo stesso? Dobbiamo anche sincronizzare il concurrenthashamp in iterazione? – user697911